150
Clean Code How to write comprehensible Code regarding cognitive abilities of human mind 01.03.2011 XPUG Rhein / Main Mario Gleichmann

Empathic Programming - How to write comprehensible code

Embed Size (px)

DESCRIPTION

Slides to a (non-commercial) talk i gave 2011 at XPUG Rhein/Main (Germany) about how to write comprehensible code, regarding cognitive abilities of human mind.

Citation preview

Page 1: Empathic Programming - How to write comprehensible code

Clean Code

How to write comprehensible Code

regarding cognitive abilities of human mind

01.03.2011

XPUG Rhein / MainMario Gleichmann

Page 2: Empathic Programming - How to write comprehensible code

Mario Gleichmann

twitter: @mariogleichmann

blog: gleichmann.wordpress.com (brain driven development)

site: www.mg-informatik.de

mail: [email protected]

Page 3: Empathic Programming - How to write comprehensible code
Page 4: Empathic Programming - How to write comprehensible code
Page 5: Empathic Programming - How to write comprehensible code

The cost of Software Development

Page 6: Empathic Programming - How to write comprehensible code

''Making changes is generally easy

if you exactly know what needs to be changed''

Intellectual Complexity

Page 7: Empathic Programming - How to write comprehensible code

Programming is a cognitive process

Page 8: Empathic Programming - How to write comprehensible code

Functionality

Page 9: Empathic Programming - How to write comprehensible code

Intellectually manageable programs

Simplicity

Page 10: Empathic Programming - How to write comprehensible code

Communication

'existing code is much more read than new code is written'

Page 11: Empathic Programming - How to write comprehensible code

Fear

Page 12: Empathic Programming - How to write comprehensible code

Empathy

Page 13: Empathic Programming - How to write comprehensible code

Cognition

Page 14: Empathic Programming - How to write comprehensible code
Page 15: Empathic Programming - How to write comprehensible code
Page 16: Empathic Programming - How to write comprehensible code
Page 17: Empathic Programming - How to write comprehensible code
Page 18: Empathic Programming - How to write comprehensible code
Page 19: Empathic Programming - How to write comprehensible code
Page 20: Empathic Programming - How to write comprehensible code

Capacity

Page 21: Empathic Programming - How to write comprehensible code
Page 22: Empathic Programming - How to write comprehensible code
Page 23: Empathic Programming - How to write comprehensible code

Chunking

Page 24: Empathic Programming - How to write comprehensible code
Page 25: Empathic Programming - How to write comprehensible code
Page 26: Empathic Programming - How to write comprehensible code
Page 27: Empathic Programming - How to write comprehensible code
Page 28: Empathic Programming - How to write comprehensible code
Page 29: Empathic Programming - How to write comprehensible code
Page 30: Empathic Programming - How to write comprehensible code
Page 31: Empathic Programming - How to write comprehensible code
Page 32: Empathic Programming - How to write comprehensible code
Page 33: Empathic Programming - How to write comprehensible code
Page 34: Empathic Programming - How to write comprehensible code
Page 35: Empathic Programming - How to write comprehensible code
Page 36: Empathic Programming - How to write comprehensible code
Page 37: Empathic Programming - How to write comprehensible code
Page 38: Empathic Programming - How to write comprehensible code

Cognitive overload

Page 39: Empathic Programming - How to write comprehensible code

Knowledge base

Page 40: Empathic Programming - How to write comprehensible code

Working Memory

Page 41: Empathic Programming - How to write comprehensible code

Program Comprehension

Page 42: Empathic Programming - How to write comprehensible code

def find( start :Char, end :Char, pths :List[ (Char,Char) ] ) :List[ (Char,Char) ] = {

var rout = (start,start) :: Nilvar dends :List[(Char,Char)] = Nil

while( !rout.isEmpty && rout.head._2 != end ){

var conts = from( rout.head._2, pths ).filter( pth => !dends.contains( pth ) && !rout.contains( pth ) )

if( conts.isEmpty && !rout.isEmpty ) {

dends = rout.head :: derout = rout.tail

}else{

rout = conts.iterator.next :: rte}

}rout.reverse.tail

}

What's the goal ?

Page 43: Empathic Programming - How to write comprehensible code

Program model

Page 44: Empathic Programming - How to write comprehensible code

Bottom up

Page 45: Empathic Programming - How to write comprehensible code

Goals & sub-goals

Page 46: Empathic Programming - How to write comprehensible code

Top down

Page 47: Empathic Programming - How to write comprehensible code

Domain Model

Page 48: Empathic Programming - How to write comprehensible code

'A'

'G'

'B'

'C'

'D'

'F'

'E''G'

'H'

'I'

Page 49: Empathic Programming - How to write comprehensible code

def findRoute( start :WayPoint, target :WayPoint, map :Set[Path] ) :Sequence[Path] = {

var route = new Stack[Path] var deadEnds :Set[Path] = new HashSet[Path]

route push Path( start, start )

while( !route.isEmpty && route.top.endPoint != target ){

var continuingPaths = pathsFrom( route.top.endPoint, map ).without( deadEnds ).without( route )

if( continuingPaths.isEmpty && !route.isEmpty ) {

deadEnds += route.pop}else{

route push continuingPaths.first}

}route.reverse

}

What's the goal ?

Page 50: Empathic Programming - How to write comprehensible code

Hypothesis &

Verification

Page 51: Empathic Programming - How to write comprehensible code

Plans & beacons

Page 52: Empathic Programming - How to write comprehensible code

public class PrimeGenerator {

static int[] sieveUpTo( int maxValue ){

if( maxValue < 2 ) return new int[0];

boolean[] grid = new boolean[maxValue + 1];for( int i = 0; i <= maxValue; i++ ){

grid[i] = true;}

grid[0] = grid[1] = false;

for( int i = 2; i < Math.sqrt( maxValue + 1 ) + 1; i++ ){if( grid[i] ){

for( int j = 2*i; j <= maxValue; j += i ){grid[j] = false;

}}

}…

}

Page 53: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Mental Model

Page 54: Empathic Programming - How to write comprehensible code

C o n c e p t s

Page 55: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Concepts

Stack

Page 56: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Concepts

Stack

Push

Pop

Page 57: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Concepts

Stack

Push

Pop

Store

Page 58: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Concepts

Stack

Push

Pop

StoreNot

'lose'Elements

Page 59: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Concepts

Stack

Push

Pop

StoreNot

'lose'Elements

Collection

Page 60: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Stack

Concepts

Store

Collection

Add Elements

Remove Elements

Not'lose'

Elements

Iterate Elements

Push

Pop

Not'lose'

Elements

Page 61: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Stack

Concepts

Store Push

Pop

LIFO

Page 62: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Stack

Concepts

Store Push

Pop

LIFO

FIFO

Page 63: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

FIFO

Stack

Concepts

Store Push

Pop

LIFO

FIFOQueue

Store

Page 64: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

FIFO

Stack

Concepts

Store Push

Pop

LIFO

FIFOQueue

Store

Add Elements

Add Elements

Collection

Add Elements

Page 65: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Assimilation

Page 66: Empathic Programming - How to write comprehensible code

public class Folding {

public static <T> T fold( List<T> list, Monoid<T> monoid ){

return list.isEmpty() ?

monoid.unit() :

monoid.conjunct( head( list ), fold( tail( list ), monoid ) );}

private static <T> T head( List<T> list ){return list.isEmpty() ? null : list.get( 0 );

}

private static <T> List<T> tail( List<T> list ){return list.size() >= 2 ? list.subList( 1, list.size() ) : EMPTY_LIST;

}}

Page 67: Empathic Programming - How to write comprehensible code

public interface Monoid<T> {

public T unit();

public T conjunct( T t1, T t2 );}

Page 68: Empathic Programming - How to write comprehensible code

public class MonoidInstanceTest extends TestCase{...

public void testStringAsMonoid(){assertEquals( "helloworld", stringMonoid.conjunct( "hello", "world" ) );assertEquals( "hollamundo", stringMonoid.conjunct( "hola", "mundo" ) );

assertEquals( "hola", stringMonoid.conjunct( "hola", stringMonoid.unit() ) );assertEquals( "hola", stringMonoid.conjunct( stringMonoid.unit(), "hola" ) );

}

public void testIntegerAsMonoid(){assertEquals( 6, poductIntMonoid.conjunct( 2, 3 ) );assertEquals( 42 , productIntMonoid.conjunct( 7, 6 ) );

assertEquals( 11, productIntMonoid.conjunct( 11, productIntMonoid.unit() ) );assertEquals( 11, productIntMonoid.conjunct( productIntMonoid.unit(), 11 ) );

}...}

Page 69: Empathic Programming - How to write comprehensible code

public class MonoidTest extends TestCase{... private static <T> void assertAssociativity( Monoid<T> monoid, T t1, T t2, T t3 ){

assertEquals( monoid.conjunct( t1, monoid.conjunct( t2, t3 ) ), monoid.conjunct( monoid.conjunct( t1, t2 ), t3 ) );

}

private static <T> void assertNeutrality( Monoid<T> monoid, T value ){

assertEquals( monoid.conjunct( value, monoid.unit() ), value );assertEquals( monoid.conjunct( monoid.unit(), value ), value );

}

public void testMonoidInstances(){assertAssociativity( stringMonoid, "s1", "s2", "s3" );assertNeutrality( stringMonoid, "s1" );...assertAssociativity( productSumMonoid, 1, 2, 3 );assertNeutrality( productSumMonoid, 1 );

}}

Page 70: Empathic Programming - How to write comprehensible code

public class Monoids {

public static Monoid<String> stringMonoid = new Monoid<String>(){

public String unit() { return ""; }

public String conjunct(String t1, String t2) { return t1 + t2; }};

public static Monoid<Integer> productIntMonoid = new Monoid<Integer>(){

public Integer unit() { return 1; }

public Integer conjunct(Integer t1, Integer t2) { return t1 * t2; }};

...

Page 71: Empathic Programming - How to write comprehensible code

public class Monoids {

...

public static Monoid<Integer> sumIntMonoid = new Monoid<Integer>(){

public Integer unit() { return 0; }

public Integer conjunct(Integer t1, Integer t2) { return t1 + t2; }};

...

Page 72: Empathic Programming - How to write comprehensible code

public class FoldTest extends TestCase{

public void testStringConcat(){

assertEquals( "Hello world !!!",fold( asList( "Hello", " ", "world" + " " + "!!!" ), stringMonoid ) );

}

public void testSum(){

assertEquals( 15, fold( asList( 1, 2, 3, 4, 5 ), sumIntMonoid ).intValue() );}

public void testProduct(){

assertEquals( 120, fold( asList( 1, 2, 3, 4, 5 ), productIntMonoid ).intValue() );}

...

Page 73: Empathic Programming - How to write comprehensible code
Page 74: Empathic Programming - How to write comprehensible code

public reorderBook( String isbn ){ ...

if( isbn.substring( 0, 2 ).equals( ''978'' ){

pubNr = isbn.substring( 6, 10 );}else{

pubNr = isbn.substring( 8, 12 );}...

}

Page 75: Empathic Programming - How to write comprehensible code

public reorderBook( String isbn ){ ...

if( isbn.substring( 0, 2 ).equals( ''978'' ){

pubNr = isbn.substring( 6, 10 );}else{

pubNr = isbn.substring( 8, 12 );}...

} ISBN is NOT a String !!!

Page 76: Empathic Programming - How to write comprehensible code

public interface Isbn {public Region getRegion(){ ... }public Integer getPublisherNumber(){ ... }

public Integer getTitelNumber(){ ... }public Integer getChecksum(){ ... }public boolean isValid(){ ... }

}

public reorderBook( Isbn isbn ){...isbn.getPublisherNumber();...

}

ISBN is a concept in its own right !!!

Page 77: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

ContureBoundary&

Page 78: Empathic Programming - How to write comprehensible code

public boolean isValidLaufzeit( Vertrag vertrag ){

GregorianCalendar start = vertrag.getStart();GregorianCalendar end = vertrag.getEnd();

int tagesdifferenz = 0;if (start != null && end != null) {

int startJahr = start.get(Calendar.YEAR);int endJahr = end.get(Calendar.YEAR);int tageImStartJahr = start.get(Calendar.DAY_OF_YEAR);int tageImEndJahr = end.get(Calendar.DAY_OF_YEAR);int aktuellesJahr = startJahr;

while (aktuellesJahr <= endJahr) {if (aktuellesJahr == startJahr) {

if (aktuellesJahr == endJahr) {tagesdifferenz += tageImEndJahr - tageImStartJahr;

} else {tagesdifferenz += start.isLeapYear(startJahr) ?

(366 - tageImStartJahr) : (365 - tageImStartJahr);}

} else if (aktuellesJahr == endJahr) {tagesdifferenz += tageImEndJahr;

} else {tagesdifferenz += start.isLeapYear(aktuellesJahr) ? 366 : 365;

}aktuellesJahr++;

}}return tagesdifferenz > 365 && tagesdifferenz < 999;

}

Page 79: Empathic Programming - How to write comprehensible code

public void createOrder( int itemId, Date shippingDate ){

Date today = new Date();

long start = today.getTime();long end = shippingDate.getTime();

BigDecimal diff = new BigDecimal( start - end );

int days = diff.divideToIntegralValue( new BigDecimal( 1000 * 60 * 60 * 24 ) ).intValue();

if( days > 14 ) rejectOrder();

// ...}

Page 80: Empathic Programming - How to write comprehensible code

Don't repeat yourself

Page 81: Empathic Programming - How to write comprehensible code

Single Source of Truth

Page 82: Empathic Programming - How to write comprehensible code

public boolean isValidLaufzeit( Vertrag vertrag ){

TimeInterval interval = vertrag.getLaufzeit();

return interval.toDuration().inYears() > ONE_YEAR && interval.toDuration().inYears() < THREE_YEARS;

}

Page 83: Empathic Programming - How to write comprehensible code

public void createOrder( int ItemId, Date shippingDate ){

Duration duration = new Duration( today(), shippingDate );

if( duration.inDays() > 14 ) rejectOrder();

// ...}

Page 84: Empathic Programming - How to write comprehensible code

Tell ! Don't ask

Page 85: Empathic Programming - How to write comprehensible code

String separator ='' '';

String query = ''select '';

if( ... ) query += '' name '';

if( ... ) query = query + separator + '' alter '', separator = '', '';

query += '' from person '';

if( existFilter ){

query += '' where ''

if( ... ) query += '' stadt = '' + stadt; separator = '' and '';else{

query += '' stadt in ( '';

for( String stadt : staedte )query += stadt + inSeparator; inSeparator = '', '';

query += '' ); separator = '' and ''}

...

Page 86: Empathic Programming - How to write comprehensible code

String separator ='' '';

String query = ''select '';

if( ... ) query += '' name '';

if( ... ) query = query + separator + '' alter '', separator = '', '';

query += '' from person '';

if( existFilter ){

query += '' where ''

if( ... ) query += '' stadt = '' + stadt; separator = '' and '';else{

query += '' stadt in ( '';

for( String stadt : staedte )query += stadt + inSeparator; inSeparator = '', '';

query += '' ); separator = '' and ''}

...

Do you see the core idea ?(Hint: it's NOT about String Handling)

Page 87: Empathic Programming - How to write comprehensible code

String separator ='' '';

String query = ''select '';

if( ... ) query += '' name '';

if( ... ) query = query + separator + '' alter '', separator = '', '';

query += '' from person '';

if( existFilter ){

query += '' where ''

if( ... ) query += '' stadt = '' + stadt; separator = '' and '';else{

query += '' stadt in ( '';

for( String stadt : staedte )query += stadt + inSeparator; inSeparator = '', '';

query += '' ); separator = '' and ''}

...

Building SQL-Statements ...… is NOT about String Handling

Page 88: Empathic Programming - How to write comprehensible code

Encapsulation

Page 89: Empathic Programming - How to write comprehensible code

Query personQuery = Query.onTable( ''Person'' )

personQuery.select( ''name'' )

personQuery.select( ''alter '' )

personQuery.add( criteria( ''stadt'' ).equals( stadt ) );

personQuery.add( criteria( ''stadt'' ).in( staedte ) );

...

Page 90: Empathic Programming - How to write comprehensible code

PIE Principle

Page 91: Empathic Programming - How to write comprehensible code

SEP Principle

Page 92: Empathic Programming - How to write comprehensible code

String separator ='' '';

String query = ''select '';

if( ... ) query += '' name '';

if( ... ) query = query + separator + '' alter '', separator = '', '';

query += '' from person '';

if( existFilter ){

query += '' where ''

if( ... ) query += '' stadt = '' + stadt; separator = '' and '';else{

query += '' stadt in ( '';

for( String stadt : staedte )query += stadt + inSeparator; inSeparator = '', '';

query += '' ); separator = '' and ''}

...

… by the way ...

Page 93: Empathic Programming - How to write comprehensible code

String separator ='' '';

String query = ''select '';

if( ... ){ query += '' name ''; separator = '', ''; }

if( ... ) query = query + separator + '' alter '', separator = '', '';

query += '' from person '';

if( existFilter ){

query += '' where ''

if( ... ) query += '' stadt = '' + stadt; separator = '' and '';else{

query += '' stadt in ( '';

for( String stadt : staedte )query += stadt + inSeparator; inSeparator = '', '';

query += '' ); separator = '' and ''}

...

… anybody missed that ?

Page 94: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Abstraction

Page 95: Empathic Programming - How to write comprehensible code

''Look, a Composite ...'

Directory

File File Directory

File File

''delete'

''delete' ''delete'

''delete'

''delete' ''delete'

Page 96: Empathic Programming - How to write comprehensible code

''Look, another Composite ...''

UI Panel

UI Text UI Input UI Panel

UI Text UI Selection

''draw' ''draw'

''draw'

''draw'

''draw'

''draw'

Page 97: Empathic Programming - How to write comprehensible code

AbstractComposite

operation()add( Composite)remove( Composite )childs() : List<Comp.>

Composite

operation()add( Composite)remove( Composite )childs() : List<Comp.>

Node

operation()

Page 98: Empathic Programming - How to write comprehensible code

Is this a Composite ?

AtLeastOneAuthProvider

LdapAuthProvider DatabaseAuth. UnanimousAuthProvider

CertificateAuth. AccessAuth.

''authenticate' ''authenticate'

''authenticate' ''authenticate'

''authenticate'

Page 99: Empathic Programming - How to write comprehensible code

... and this ?

CEO

Employee Employee CIO

Employee Employee

''salary' ''salary'

''salary' ''salary'

''salary'

Page 100: Empathic Programming - How to write comprehensible code
Page 101: Empathic Programming - How to write comprehensible code

Collection

Queue

List

Stack

Set Bag

generalization

< discrimination >

FIFO LIFO

Page 102: Empathic Programming - How to write comprehensible code

public static Integer sum( Stack<Integer> vals ){

int sum = 0;

for( int val : vals ) sum += val;

return sum;}

Page 103: Empathic Programming - How to write comprehensible code

public static Integer sum( Stack<Integer> vals ){

int sum = 0;

for( int val : vals ) sum += val;

return sum;}

sum( new Stack<Integer>(){{ push(1); push(2); push(3); }};

sum( new ArrayList<Integer>(){{ add(1); add(2); add(3) }};

Page 104: Empathic Programming - How to write comprehensible code

public static Integer sum( List<Integer> vals ){

int sum = 0;

for( int val : vals ) sum += val;

return sum;}

sum( new Stack<Integer>(){{ push(1); push(2); push(3); }};

sum( new ArrayList<Integer>(){{ add(1); add(2); add(3) }};

sum( new HashSet<Integer>(){{ add(1); add(2); add(3) }};

Page 105: Empathic Programming - How to write comprehensible code

public static Integer sum( Collection<Integer> vals ){

int sum = 0;

for( int val : vals ) sum += val;

return sum;}

sum( new Stack<Integer>(){{ push(1); push(2); push(3); }};

sum( new ArrayList<Integer>(){{ add(1); add(2); add(3) }};

sum( new HashSet<Integer>(){{ add(1); add(2); add(3) }};

Page 106: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Adaption

Page 107: Empathic Programming - How to write comprehensible code

public class QueueTest extends TestCase {

private Queue<Integer> queue = null;

public void setUp() throws Exception{

queue = new ...

queue.add( 10 );queue.add( 3 );queue.add( 7 );queue.add( 5 );

}

public testQueuePolling{

assertEquals( ? , queue.poll() );assertEquals( ?? , queue.poll() );assertEquals( ??? , queue.poll() );assertEquals( ???? , queue.poll() );

}}

Page 108: Empathic Programming - How to write comprehensible code

public class QueueTest extends TestCase {

private Queue<Integer> queue = null;

public void setUp() throws Exception{

queue = new ArrayBlockingQueue<Integer>();

queue.add( 10 );queue.add( 3 );queue.add( 7 );queue.add( 5 );

}

public testQueuePolling{

assertEquals( 10 , queue.poll() );assertEquals( 3 , queue.poll() );assertEquals( 7 , queue.poll() );assertEquals( 5 , queue.poll() );

}}

Page 109: Empathic Programming - How to write comprehensible code

public class QueueTest extends TestCase {

private Queue<Integer> queue = null;

public void setUp() throws Exception{

queue = new PriorityQueue<Integer>();

queue.add( 10 );queue.add( 3 );queue.add( 7 );queue.add( 5 );

}

public testQueuePolling{

assertEquals( 3 , queue.poll() );assertEquals( 5 , queue.poll() );assertEquals( 7 , queue.poll() );assertEquals( 10 , queue.poll() );

}}

Page 110: Empathic Programming - How to write comprehensible code

Accomodation

Page 111: Empathic Programming - How to write comprehensible code

Collection

Queue

List

Stack

Set Bag

generalization

< discrimination > FIFOHPFO

PriorityQueue ArrayQueue

Page 112: Empathic Programming - How to write comprehensible code

Appropriateness

Page 113: Empathic Programming - How to write comprehensible code

public static List<Integer> multiplesOf( int factor, int limit ){

List<Integer> collect = new ArrayList<Integer>();

for( int i = 1; i * factor <= limit; i++ ){collect.add( i * factor );

}return collect;

}

vs.

public static Set<Integer> multiplesOf( int factor, int limit ){

Set<Integer> collect = new HashSet<Integer>();

for( int i = 1; i * factor <= limit; i++ ){collect.add( i * factor );

}return collect;

}

Page 114: Empathic Programming - How to write comprehensible code

public static List<Integer> multiplesOf( int[] factors, int limit ){

List<Integer> collect = new ArrayList<Integer>();

for( int factor : factors ){

for( int i = 1; i * factor <= limit; i++ ){

collect.add( i * factor );}

}return collect;

}

Page 115: Empathic Programming - How to write comprehensible code

public static Set<Integer> multiplesOf( int[] factors, int limit ){

Set<Integer> collect = new HashSet<Integer>();

for( int factor : factors ){

for( int i = 1; i * factor <= limit; i++ ){

collect.add( i * factor );}

}return collect;

}

Page 116: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Re - Cognition

Page 117: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){

BigDecimal totalCost = initialCost.add( runCost );

BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) );

BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN );

return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}

Page 118: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){

BigDecimal totalCost = initialCost.add( runCost );

BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) );

BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN );

return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}

BigDecimal as Money

Page 119: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){

BigDecimal totalCost = initialCost.add( runCost );

BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) );

BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN );

return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}

BigDecimal as Percent

Page 120: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){

BigDecimal totalCost = initialCost.add( runCost );

BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) );

BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN );

return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}

What's the result 'type' of combining 'Money' with 'Percent'

Page 121: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){

BigDecimal totalCost = initialCost.add( runCost );

BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) );

BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN );

return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}

Which combinations are allowed -which not ?

Page 122: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

LiM Principle

Page 123: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Distinction

public boolean isGoodDeal( Money initialCosts, Money runCosts ){

Money totalCost = initialCosts.sum( runCosts );

Percent proportionRunCosts = totalCost.proportionOf( runCost )

return proportionRunCosts.isGreaterThan( Percent.FIFTY )}

Page 124: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Single Responsibility Principle

Page 125: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Page 126: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Mental DistanceMental Distance

Page 127: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

interface Stepper<T>{

public boolean isExhausted();

public void step();

public T getCurrent()}

... do you recognize the underlying concept ?

Page 128: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

interface ElementSupplier<T>{

public boolean hasMoreElements();

T nextElement();}

... do you recognize the underlying concept ?

Page 129: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

interface ElementConsumer{

public void observe( BigElement e );

public void calculate( AnotherElement e );

public void extract( YetAnotherElement );}

... do you recognize the underlying concept ?

Page 130: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

interface ElementInspector{

public void inspect( BigElement e );

public void inspect( AnotherElement e );

public void inspect( YetAnotherElement );}

... do you recognize the underlying concept ?

Page 131: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

interface ElementVisitor{

public void visit( BigElement e );

public void visit( AnotherElement e );

public void visit( YetAnotherElement );}

... do you recognize the underlying concept ?

Page 132: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

date.compareTo( otherDate ) < 0

vs.

date.isBefore( otherDate )

Language

Page 133: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Code slicing

Page 134: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Locality

Page 135: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Trust

Page 136: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Verifiable SpecificationsStack stack = is( new DescriptionOf <Stack>(){

public Stack isDescribedAs(){

Stack<String> stack = new Stack<String>(); stack.push( foo ); stack.push( bar ); return stack; } } );

it( "should contain foo" ); state( stack ).should( contain( foo ) ); it( "should contain bar" ); state( stack ).should( contain( bar ) ); it( "should return bar when calling pop the first time" ); state( stack.pop() ).should( returning( bar ) ); it( "should return foo when calling pop the second time" ); stack.pop(); state( stack.pop() ).should( returning( foo ) ); it( "should be empty after popping the two elements" ); stack.pop(); stack.pop(); state( stack ).should( be ( empty() ) );

Page 137: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Design by Contract@Invariant( "this.size >= 0 and this.size <= this.capazity" )public interface Stack { ... }

@Postcondition( "return > 0" )public int getCapacity();

public int getSize();

@Precondition( "elem not null and this.size < this.capacity" )@Postcondition( "elem == this.top and this.size == old:this.size + 1" )public void push( Object elem );

@Postcondition( "this.top == old:this.top ) " )public Object getTop();

@Postcondition( "(old:this.size>0) ==> (return == old:this.top and this.size == old:this.size - 1)")public Object pop();

...}

Page 138: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

''if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties''

Liskov Substitution Principle

Page 139: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Open Closed Principle

Page 140: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Principle of least astonishment

Page 141: Empathic Programming - How to write comprehensible code

Mario Gleichmann MG Informatik

Symmetry & balance

Page 142: Empathic Programming - How to write comprehensible code

...

void writeToFile( Output outout ){

openFile();

writeToFile( output );

}

Page 143: Empathic Programming - How to write comprehensible code

void process{

input();

count++;

output();}

Page 144: Empathic Programming - How to write comprehensible code

One level of abstraction

Page 145: Empathic Programming - How to write comprehensible code

Expressiveness

Intention Revealing Interfaces

Immutabilityside effects

declarative vs

imperative

Domain Driven DesignConsistence

Yagni

Dependency Inversion Principle

Functional Programming

Page 146: Empathic Programming - How to write comprehensible code

If there are three things to keep in mind ...

Page 147: Empathic Programming - How to write comprehensible code

… it's not only ''developers! developers! developers!'' ...

Page 148: Empathic Programming - How to write comprehensible code

… but

Empathy!

Empathy!

Empathy!

Page 149: Empathic Programming - How to write comprehensible code

Now stop hacking code for machines

start writing programs for humans

… and the rest will follow ...

Page 150: Empathic Programming - How to write comprehensible code