54
Keeping Code Clean Agile tools and practices for better code

Keeping code clean

Embed Size (px)

DESCRIPTION

One of the main hindrances to teams being able to respond rapidly to new features are technical problems resulting from bad coding practices, also known as technical debt. Melissa and Brett will cover Agile tools and practices that help development teams write better code and increase maintainability. Topics that will be covered include: Pair programming Automated Unit Testing Refactoring Test-Driven Development Agile Architecture

Citation preview

Page 1: Keeping code clean

Keeping Code CleanAgile tools and practices for better code

Page 2: Keeping code clean

Topics

● Pair Programming● Automated Unit Testing● Refactoring● Test-Driven Development● Agile Architecture

Page 3: Keeping code clean

Pair Programming

Page 4: Keeping code clean

Pair Programming

Page 5: Keeping code clean

● Continuous Code Review● Better Design w/ Less Code● Faster Problem Solving● More People Familiar w/ System● Team Grows Closer

Pair Programming - Benefits

Page 6: Keeping code clean

Pair Programming - Evidence

Page 7: Keeping code clean

Pair Programming - Evidence

Williams 2000● Efforts +15%, Schedule -43%Baheti 2002● Effort +2%, Schedule -49%Ciokowlski 2002● Effort +9%, Schedule -46%

Page 8: Keeping code clean

Automated Unit Testing

Page 9: Keeping code clean

What is Automated Unit Testing?

Use of special software to control the execution of unit tests and the comparison of actual outcomes with predicted outcomes.

To get full benefit run as part of the build process and schedule to run automatically once or twice a day.

Page 10: Keeping code clean

Automated Unit Test Suite Benefits● Unit tests find problems early in the development cycle● Developers will be less afraid to change code● Development process becomes more flexible● Easier for a developer to take over code they are

unfamiliar with (improves “Truck Factor”)● Reduces need for manual testing● Software development becomes more testable and

repeatable

Page 11: Keeping code clean

What is a Unit Test Case?

● A test for a single unit of functionality● Each method tests a specific bit of

functionality● Automated by the test-runner framework

Page 12: Keeping code clean

AAA Test Structure

● Structure:○ Arrange○ Act○ Assert

● Benefits:○ Readable○ Consistent

public class SalesTaxTest

{

private SalesTax unit;

@Test

public void TestCalculate()

{

unit = new SalesTax(); // ARRANGE

double tax = unit.Calculate(10); // ACT

Assert.assertEquals(tax, 0.9); // ASSERT

}

}

Page 13: Keeping code clean

Unit Testing Best Practices

● Test simple stuff first ● Get it working - then test boundaries/exceptions● Use assert ● Keep tests small & understandable● Make test method names descriptive● Keep tests independent of each other● Avoid System.out messages● Don’t repeat tests! Test once and trust it.

Page 14: Keeping code clean

Test Doubles

● Stand in for a collaborating object e.g. database, webservice

● Create test independence● Make tests run faster● Types of Doubles

○ Fakes: working implementation e.g.fake web service○ Mocks: preprogrammed with expectations○ Stubs: provide canned answers to the test’s calls

Page 15: Keeping code clean

Refactoring

Page 16: Keeping code clean

Refactoring

● What is refactoring?● Why refactor?● When to refactor?

Page 17: Keeping code clean

What is Refactoring?

“A change to the system that leaves its behavior unchanged, but enhances some non-functional quality - simplicity, flexibility, understandability, performance”

-- Kent Beck, Extreme Programing Explained (p. 179)

“A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.”

-- Martin Fowler, Refactoring (p. 53)

Page 18: Keeping code clean

Why Refactor the Code?

● Prevent “design decay”● Clean up messes● Simplify● Increase readability / understandability● Find bugs● Reduce debugging time● Build in what we learn about the application● It’s part of the creative process

Page 19: Keeping code clean

When to Refactor

● Code reviews / TDD cycle● Rule of three

○ cut & paste. Third time copying? Now is the time to generalize and move this to a new procedure.

● When you:○ add functionality○ learn something about the code○ identify a code smell

Page 20: Keeping code clean

What is a Code Smell?

● any symptom in the code that possibly indicates a deeper problem.

● not bugs - but indicate weaknesses in design that may be slowing down development or increasing the risk of bugs or failures in the future.

Page 21: Keeping code clean

Code Smells (1/2)● Duplicated code: near-identical code in multiple places● Long method: a too large method/function/procedure ● Large class: a class that has grown too large. ● Too many parameters: decreases readability/quality.● Identifier names are too short or excessively long● Complex conditionals: branches that check lots of

unrelated conditions and edge cases that don't seem to capture the meaning of a block of code.

Page 22: Keeping code clean

Code Smells (2/2)● Comments - refactor so these are no longer needed!● Feature envy: excessive use of another class’ methods● Inappropriate intimacy: a class that has dependencies

on implementation details of another class.● Lazy class / Freeloader: a class that does too little.● Contrived complexity: simpler design would suffice.● Excessive use of literals (use named constants)

Page 23: Keeping code clean

Why Developers Resist Refactoring

● Lack of understanding● Short-term focus● Not paid for overhead tasks like refactoring● Fear of breaking current program

Use TDD to overcome this fear!

Page 24: Keeping code clean

Test-Driven Development

Page 25: Keeping code clean

TDD as a Design Approach

● Tests define up front what “works” means● Programing by intention - write tests for what

code intends to do not what the code you just wrote does.

● Focus on minimum set of required features● Regular integration of small changes● Evolutionary Design: Tests provide a safety

net for refactoring.

Page 26: Keeping code clean

Red-Green-Refactor Cycle

Page 27: Keeping code clean

How to Get to Green? Implement it!

Obvious Implementation

code the real implementation, if it's obvious and can quickly make test pass, otherwise...

public int Sum(int x, int y)

{

return x + y;

}

Page 28: Keeping code clean

How to Get to Green? Fake it

Fake it

hardcode constants to make test pass, gradually generalize code using variables

public int Fibonacci(int n)

{

if (n >= 1) return 1;

return 0;

}

Page 29: Keeping code clean

How to Get to Green? Triangulate

Triangulate

figure out the behavior of an algorithm by examining a couple of test cases instead of just one.

public void TestSum()

{

Assert.AreEqual(4, Plus(3, 1));

Assert.AreEqual(7, Plus(4, 3));

}

Page 30: Keeping code clean

Use TDD to Earn a Gift Card! TDD is a great tool to use in solving the code challenges. E.g. Function takes a Roman Numeral String and returns the Decimal value.● Start with simple valid numbers I, III... up to more complex tests● Incorporate tests for boundary conditions and invalid numbers● With a set of tests you can easily refactor your solution.

VALID NUMBERS INVALID NUMBERS

I Boundary: Empty, 0, MMMM

III iii

IV IVIV, IIII, IIX, MXXXX

VI, XLIX, MMMDCCCLXXXVIII ABCDEF

Page 31: Keeping code clean

A Great TDD Example!

● Bowling Kata - how to score a bowling game.

● Eclipse and junit step-by-step presentation on red - green - refactor to solve (butunclebob.

com/files/downloads/Bowling%20Game%20Kata.ppt)

Page 32: Keeping code clean

Agile Architecture

Page 33: Keeping code clean

● Collaborative Design● Good coding Standards and Principles

Agile Architecture

Page 34: Keeping code clean

Collaborative Design

● Emergent Design○ Light Design Up Front (LDUF)

● Every team member contributes● No command and control

Page 35: Keeping code clean

Collaborative Design - payoff

http://martinfowler.com/bliki/DesignStaminaHypothesis.html

Page 36: Keeping code clean

Standards and Principles

● Agree as a team○ coding and naming conventions○ toolset

■ Static Code Analysis, Test mocks, etc○ best practices

● Avoid Technical Debt● Follow well established principles and

patterns

Page 37: Keeping code clean

Object Oriented Design Principles

S ingle Responsibilty O pen/ClosedL iskov SubstitutionI nterface SegregationD ependency Inversion

Page 38: Keeping code clean
Page 39: Keeping code clean

The Single Responsibility Principle● Every class should have a single responsibility, and that responsibility

should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

● Single Reason to Change

Page 40: Keeping code clean

class Book { function getTitle() { return "A Great Book"; } function getAuthor() { return "John Doe"; } function turnPage() { // pointer to next page } function printCurrentPage() { echo "current page content"; }}

Page 41: Keeping code clean
Page 42: Keeping code clean

The Open/Closed Principle

● You should be able to extend a classes behavior without modifying it

● Open for extension, but closed for modification

Page 43: Keeping code clean

public double Area(object[] shapes){ double area = 0; foreach (var shape in shapes) { if (shape is Rectangle) { Rectangle rectangle = (Rectangle) shape; area += rectangle.Width*rectangle.Height; } else { Circle circle = (Circle)shape; area += circle.Radius * circle.Radius * Math.PI; } }

return area;}

Page 44: Keeping code clean
Page 45: Keeping code clean

The Liskov Substitution Principle

● Derived classes must be substitutable for their base classes

Page 46: Keeping code clean

public class Rectangle {private int width;private int height;

// setters and getters}

public class Square extends Rectangle {public Square(int height, int width) {

setWidth(width);setHeight(height);

}}

Page 47: Keeping code clean
Page 48: Keeping code clean

The Interface Segregation Principle

● No client should be forced to depend on methods it does not use

Page 49: Keeping code clean

interface Worker {void work();void eat();

}

class HumanWorker implements Worker {Public void work { /* do work stuff */ }Public void eat { /* eat stuff */ }

}

class RobotWorker implements Worker {Public void work { /* do work stuff */ }Public void eat { /* ACK! I don't eat! */ }

}

interface Worker {

void work();

}

interface Eater {

void eat();

}

class HumanWorker implements Worker, Eater {

Public void work { /* do work stuff */ }

Public void eat { /* eat stuff */ }

}

class RobotWorker implements Worker {

Public void work { /* do work stuff */ }

}

Page 50: Keeping code clean
Page 51: Keeping code clean

The Dependency Inversion Principle

● High-level modules should not depend on low-level modules. Both should depend on abstractions.

● Abstractions should not depend on details. Details should depend on abstractions.

Page 52: Keeping code clean

class Worker {

private FileWriter fileWriter;

public Worker() {fileWriter = new FileWriter();

}

}

class Worker {

private FileWriter fileWriter;

public Worker(FIleWriter writer) {

fileWriter = writer;

}

}

interface FileWriter {

// writer files or something

}

Page 53: Keeping code clean

Object Orient Patterns

● Common Design Patterns○ Strategy, Command, Decorator, Adapter, etc

● Enterprise Integration Patterns

Page 54: Keeping code clean

AcknowledgementsPair Programming:

● http://www.cs.pomona.edu/classes/cs121/supp/williams_prpgm.pdf● http://collaboration.csc.ncsu.edu/laurie/Papers/ieeeSoftware.PDF

SOLID● http://lostechies.com/derickbailey/2009/02/11/solid-development-principles-in-motivational-

pictures/Content based on:

● SolutionsIQ CSD training slides● http://en.wikipedia.org/wiki/Code_smell● http://www.codeproject.com/Articles/5404/The-benefits-of-automated-unit-testing