Clean CodeHow to write comprehensible Coderegarding cognitive abilities of human mind01.03.2011XPUG Rhein / MainMario Glei...
Mario Gleichmanntwitter:   @mariogleichmannblog:      gleichmann.wordpress.com (brain driven development)site:      www.mg...
The cost of Software Development
Intellectual Complexity     Making changes is generally easyif you exactly know what needs to be changed
Programming is a cognitive process
Functionality
SimplicityIntellectually manageable programs
Communicationexisting code is much more read than new code is written
Fear
Empathy
Cognition
Capacity
Chunking
Cognitive overload
Knowledge base
Working Memory
Program Comprehension
Whats the goal ?def find( start :Char, end :Char, pths :List[ (Char,Char) ] ) :List[ (Char,Char) ] = {    var rout = (star...
Program  model
Bottom up
Goals   &   sub-goals
Top down
Domain Model
G                                      FI            B                  C      A                                          ...
Whats the goal ?def findRoute( start :WayPoint, target :WayPoint, map :Set[Path] ) :Sequence[Path] = {    var route = new ...
Hypothesis      &Verification
Plans & beacons
public class PrimeGenerator {    static int[] sieveUpTo( int maxValue ){    if( maxValue < 2 ) return new int[0];    boole...
Mental Model
Concepts
Concepts Stack
Concepts           Push                  Pop  Stack
ConceptsStore              Push                          Pop          Stack
Concepts               NotStore        lose   Push           Elements                             Pop          Stack
Concepts                    Not    Store         lose   Push                Elements                                  PopC...
Concepts                             Not     Store                 lose       Push                         Elements       ...
ConceptsStore              Push                          Pop         Stack                          LIFO
ConceptsStore               Push                           Pop         Stack                           LIFO               ...
ConceptsStore               Push                           Pop          Stack                           LIFO        Queue ...
Concepts     Store                    Push                                     PopCollection          Stack               ...
Assimilation
public class Folding {    public static <T> T fold( List<T> list, Monoid<T> monoid ){        return list.isEmpty() ?      ...
public interface Monoid<T> {    public T unit();    public T conjunct( T t1, T t2 );}
public class MonoidInstanceTest extends TestCase{... public void testStringAsMonoid(){      assertEquals( "helloworld", st...
public class MonoidTest extends TestCase{...  private static <T> void assertAssociativity( Monoid<T> monoid, T t1, T t2, T...
public class Monoids {   public static Monoid<String> stringMonoid = new Monoid<String>(){         public String unit() { ...
public class Monoids {   ...   public static Monoid<Integer> sumIntMonoid = new Monoid<Integer>(){         public Integer ...
public class FoldTest extends TestCase{      public void testStringConcat(){          assertEquals(     "Hello world !!!",...
public reorderBook( String isbn ){   ...    if( isbn.substring( 0, 2 ).equals( 978 ){          pubNr = isbn.substring( 6, ...
public reorderBook( String isbn ){   ...    if( isbn.substring( 0, 2 ).equals( 978 ){          pubNr = isbn.substring( 6, ...
public interface Isbn {      public Region getRegion(){ ... }      public Integer getPublisherNumber(){ ... }      public ...
Conture          &   Boundary
public boolean isValidLaufzeit( Vertrag vertrag ){     GregorianCalendar start = vertrag.getStart();     GregorianCalendar...
public void createOrder( int itemId, Date shippingDate ){    Date today = new Date();    long start = today.getTime();    ...
Dont repeat yourself
Single Source of Truth
public boolean isValidLaufzeit( Vertrag vertrag ){    TimeInterval interval = vertrag.getLaufzeit();    return        inte...
public void createOrder( int ItemId, Date shippingDate ){    Duration duration = new Duration( today(), shippingDate );   ...
Tell ! Dont ask
String separator = ;String query = select ;if( ... ) query +=  name ;if( ... ) query = query + separator +  alter , separa...
String separator = ;String query = select ;if( ... ) query +=  name ;if( ... ) query = query + separator +  alter , separa...
String separator = ;String query = select ;if( ... ) query +=  name ;if( ... ) query = query + separator +  alter , separa...
Encapsulation
Query personQuery = Query.onTable( Person )personQuery.select( name )personQuery.select( alter  )personQuery.add( criteria...
PIE Principle
SEP Principle
String separator = ;                          … by the way ...String query = select ;if( ... ) query +=  name ;if( ... ) q...
String separator = ;                    … anybody missed that ?String query = select ;if( ... ){ query +=  name ; separato...
Abstraction
Look, a Composite ...                    Directory              delete   File              File                         Di...
Look, another Composite ...              UI Panel             drawUI Text      UI Input                  UI Panel         ...
AbstractComposite         operation()         add( Composite)         remove( Composite )         childs() : List<Comp.>  ...
Is this a Composite ?                     AtLeastOneAuthProvider            authenticateLdapAuthProvider           Databas...
... and this ?             CEO               salaryEmployee     Employee                      CIOsalary    salary         ...
Collection        generalization                                List       Set   BagQueue                           Stack ...
public static Integer sum( Stack<Integer> vals ){    int sum = 0;    for( int val : vals ) sum += val;    return sum;}
public static Integer sum( Stack<Integer> vals ){    int sum = 0;    for( int val : vals ) sum += val;    return sum;}sum(...
public static Integer sum( List<Integer> vals ){    int sum = 0;    for( int val : vals ) sum += val;    return sum;}sum( ...
public static Integer sum( Collection<Integer> vals ){    int sum = 0;    for( int val : vals ) sum += val;    return sum;...
Adaption
public class QueueTest extends TestCase {    private Queue<Integer> queue = null;    public void setUp() throws Exception{...
public class QueueTest extends TestCase {    private Queue<Integer> queue = null;    public void setUp() throws Exception{...
public class QueueTest extends TestCase {    private Queue<Integer> queue = null;    public void setUp() throws Exception{...
Accomodation
Collection            generalization                                   List       Set   Bag   Queue                       ...
Appropriateness
public static List<Integer> multiplesOf( int factor, int limit ){    List<Integer> collect = new ArrayList<Integer>();    ...
public static List<Integer> multiplesOf( int[] factors, int limit ){    List<Integer> collect = new ArrayList<Integer>(); ...
public static Set<Integer> multiplesOf( int[] factors, int limit ){    Set<Integer> collect = new HashSet<Integer>();    f...
Re - Cognition
Distinctionpublic boolean isGoodDeal(     BigDecimal initialCosts,                               BigDecimal runCosts ){   ...
Distinctionpublic boolean isGoodDeal(     BigDecimal initialCosts,                               BigDecimal runCosts ){   ...
Distinctionpublic boolean isGoodDeal(     BigDecimal initialCosts,                               BigDecimal runCosts ){   ...
Distinctionpublic boolean isGoodDeal(     BigDecimal initialCosts,                               BigDecimal runCosts ){   ...
Distinctionpublic boolean isGoodDeal(     BigDecimal initialCosts,                               BigDecimal runCosts ){   ...
LiM Principle
Distinctionpublic boolean isGoodDeal( Money initialCosts, Money runCosts ){    Money totalCost = initialCosts.sum( runCost...
Single Responsibility Principle
Mental Distance  Mental Distance
... do you recognize the underlying concept ?         interface Stepper<T>{             public boolean isExhausted();     ...
... do you recognize the underlying concept ?         interface ElementSupplier<T>{             public boolean hasMoreElem...
... do you recognize the underlying concept ?       interface ElementConsumer{           public void observe( BigElement e...
... do you recognize the underlying concept ?       interface ElementInspector{           public void inspect( BigElement ...
... do you recognize the underlying concept ?       interface ElementVisitor{           public void visit( BigElement e );...
Language       date.compareTo( otherDate ) < 0                      vs.           date.isBefore( otherDate )
Codeslicing
Locality
Trust
Verifiable SpecificationsStack stack = is(             new DescriptionOf <Stack>(){                 public Stack isDescrib...
Design by Contract@Invariant( "this.size >= 0 and this.size <= this.capazity" )public interface Stack { ... }    @Postcond...
Liskovsubtype of T, then objects of type T in a  if S is a              Substitution Principle   program may be replaced w...
Open Closed Principle
Principle of least astonishment
Symmetry & balance
...void writeToFile( Output outout ){      openFile();      writeToFile( output );}
void process{    input();    count++;    output();}
One level of abstraction
Dependency Inversion Principle                                                declarative                                 ...
If there are three things to keep in mind ...
… its not only developers! developers! developers! ...
… but Empathy!   Empathy!        Empathy!
Now stop hacking code          for machines start writing programs              for humans… and the rest will follow ...
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Empathic Programming - How to write comprehensible code
Upcoming SlideShare
Loading in...5
×

Empathic Programming - How to write comprehensible code

2,546

Published on

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.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,546
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
34
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Empathic Programming - How to write comprehensible code

  1. 1. Clean CodeHow to write comprehensible Coderegarding cognitive abilities of human mind01.03.2011XPUG Rhein / MainMario Gleichmann
  2. 2. Mario Gleichmanntwitter: @mariogleichmannblog: gleichmann.wordpress.com (brain driven development)site: www.mg-informatik.demail: mario.gleichmann@mg-informatik.de
  3. 3. The cost of Software Development
  4. 4. Intellectual Complexity Making changes is generally easyif you exactly know what needs to be changed
  5. 5. Programming is a cognitive process
  6. 6. Functionality
  7. 7. SimplicityIntellectually manageable programs
  8. 8. Communicationexisting code is much more read than new code is written
  9. 9. Fear
  10. 10. Empathy
  11. 11. Cognition
  12. 12. Capacity
  13. 13. Chunking
  14. 14. Cognitive overload
  15. 15. Knowledge base
  16. 16. Working Memory
  17. 17. Program Comprehension
  18. 18. Whats the goal ?def find( start :Char, end :Char, pths :List[ (Char,Char) ] ) :List[ (Char,Char) ] = { var rout = (start,start) :: Nil var 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 :: de rout = rout.tail } else{ rout = conts.iterator.next :: rte } } rout.reverse.tail}
  19. 19. Program model
  20. 20. Bottom up
  21. 21. Goals & sub-goals
  22. 22. Top down
  23. 23. Domain Model
  24. 24. G FI B C A H D G E
  25. 25. Whats the goal ?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}
  26. 26. Hypothesis &Verification
  27. 27. Plans & beacons
  28. 28. 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; } } } …}
  29. 29. Mental Model
  30. 30. Concepts
  31. 31. Concepts Stack
  32. 32. Concepts Push Pop Stack
  33. 33. ConceptsStore Push Pop Stack
  34. 34. Concepts NotStore lose Push Elements Pop Stack
  35. 35. Concepts Not Store lose Push Elements PopCollection Stack
  36. 36. Concepts Not Store lose Push Elements PopCollection Stack Add Remove IterateElements Elements Elements
  37. 37. ConceptsStore Push Pop Stack LIFO
  38. 38. ConceptsStore Push Pop Stack LIFO FIFO
  39. 39. ConceptsStore Push Pop Stack LIFO Queue FIFO FIFO
  40. 40. Concepts Store Push PopCollection Stack LIFO AddAddAddElements Elements Elements Queue FIFO FIFO
  41. 41. Assimilation
  42. 42. 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; }}
  43. 43. public interface Monoid<T> { public T unit(); public T conjunct( T t1, T t2 );}
  44. 44. 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 ) ); }...}
  45. 45. 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 ); }}
  46. 46. 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; } }; ...
  47. 47. 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; } }; ...
  48. 48. 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() ); }...
  49. 49. public reorderBook( String isbn ){ ... if( isbn.substring( 0, 2 ).equals( 978 ){ pubNr = isbn.substring( 6, 10 ); } else{ pubNr = isbn.substring( 8, 12 ); } ...}
  50. 50. 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 !!!
  51. 51. public interface Isbn { public Region getRegion(){ ... } public Integer getPublisherNumber(){ ... } public Integer getTitelNumber(){ ... } public Integer getChecksum(){ ... } public boolean isValid(){ ... }} ISBN is a concept in its own right !!! public reorderBook( Isbn isbn ){ ... isbn.getPublisherNumber(); ... }
  52. 52. Conture & Boundary
  53. 53. 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;}
  54. 54. 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(); // ...}
  55. 55. Dont repeat yourself
  56. 56. Single Source of Truth
  57. 57. public boolean isValidLaufzeit( Vertrag vertrag ){ TimeInterval interval = vertrag.getLaufzeit(); return interval.toDuration().inYears() > ONE_YEAR && interval.toDuration().inYears() < THREE_YEARS;}
  58. 58. public void createOrder( int ItemId, Date shippingDate ){ Duration duration = new Duration( today(), shippingDate ); if( duration.inDays() > 14 ) rejectOrder(); // ...}
  59. 59. Tell ! Dont ask
  60. 60. 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 }...
  61. 61. String separator = ;String query = select ;if( ... ) query += name ;if( ... ) query = query + separator + alter , separator = , ;query += from person ; Do you see the core idea ?if( existFilter ){ (Hint: its NOT about String Handling) query += where if( ... ) query += stadt = + stadt; separator = and ; else{ query += stadt in ( ; for( String stadt : staedte ) query += stadt + inSeparator; inSeparator = , ; query += ); separator = and }...
  62. 62. String separator = ;String query = select ;if( ... ) query += name ;if( ... ) query = query + separator + alter , separator = , ;query += from person ; Building SQL-Statements ...if( existFilter ){ … is NOT about String Handling query += where if( ... ) query += stadt = + stadt; separator = and ; else{ query += stadt in ( ; for( String stadt : staedte ) query += stadt + inSeparator; inSeparator = , ; query += ); separator = and }...
  63. 63. Encapsulation
  64. 64. Query personQuery = Query.onTable( Person )personQuery.select( name )personQuery.select( alter )personQuery.add( criteria( stadt ).equals( stadt ) );personQuery.add( criteria( stadt ).in( staedte ) );...
  65. 65. PIE Principle
  66. 66. SEP Principle
  67. 67. String separator = ; … by the way ...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 }...
  68. 68. String separator = ; … anybody missed that ?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 }...
  69. 69. Abstraction
  70. 70. Look, a Composite ... Directory delete File File Directory deletedelete delete File File delete delete
  71. 71. Look, another Composite ... UI Panel drawUI Text UI Input UI Panel drawdraw draw UI Text UI Selection draw draw
  72. 72. AbstractComposite operation() add( Composite) remove( Composite ) childs() : List<Comp.> Node Compositeoperation() operation() add( Composite) remove( Composite ) childs() : List<Comp.>
  73. 73. Is this a Composite ? AtLeastOneAuthProvider authenticateLdapAuthProvider DatabaseAuth. UnanimousAuthProvider authenticate authenticate CertificateAuth. AccessAuth. authenticate authenticate
  74. 74. ... and this ? CEO salaryEmployee Employee CIOsalary salary Employee Employee salary salary
  75. 75. Collection generalization List Set BagQueue Stack < discrimination > FIFO LIFO
  76. 76. public static Integer sum( Stack<Integer> vals ){ int sum = 0; for( int val : vals ) sum += val; return sum;}
  77. 77. 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) }};
  78. 78. 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) }};
  79. 79. 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) }};
  80. 80. Adaption
  81. 81. 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() ); }}
  82. 82. 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() ); }}
  83. 83. 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() ); }}
  84. 84. Accomodation
  85. 85. Collection generalization List Set Bag Queue StackPriorityQueue ArrayQueueHPFO < discrimination > FIFO
  86. 86. Appropriateness
  87. 87. 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;}
  88. 88. 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;}
  89. 89. 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;}
  90. 90. Re - Cognition
  91. 91. Distinctionpublic 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;}
  92. 92. Distinctionpublic boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){ BigDecimal totalCost = initialCost.add( runCost ); BigDecimal oneP = totalCost.divide( new BigDecimal( 100 ) ); BigDecimal as Money BigDecimal propRunCosts = wk.divide( oneP, 2, DOWN ); return ! propRunCosts.compareTo( new BigDecimal( 50 ) ) > 1;}
  93. 93. Distinctionpublic boolean isGoodDeal( BigDecimal initialCosts, BigDecimal runCosts ){ BigDecimal as Percent 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;}
  94. 94. Distinctionpublic 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;} Whats the result type of combining Money with Percent
  95. 95. Distinctionpublic 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 ?
  96. 96. LiM Principle
  97. 97. Distinctionpublic boolean isGoodDeal( Money initialCosts, Money runCosts ){ Money totalCost = initialCosts.sum( runCosts ); Percent proportionRunCosts = totalCost.proportionOf( runCost ) return proportionRunCosts.isGreaterThan( Percent.FIFTY )}
  98. 98. Single Responsibility Principle
  99. 99. Mental Distance Mental Distance
  100. 100. ... do you recognize the underlying concept ? interface Stepper<T>{ public boolean isExhausted(); public void step(); public T getCurrent() }
  101. 101. ... do you recognize the underlying concept ? interface ElementSupplier<T>{ public boolean hasMoreElements(); T nextElement(); }
  102. 102. ... do you recognize the underlying concept ? interface ElementConsumer{ public void observe( BigElement e ); public void calculate( AnotherElement e ); public void extract( YetAnotherElement ); }
  103. 103. ... do you recognize the underlying concept ? interface ElementInspector{ public void inspect( BigElement e ); public void inspect( AnotherElement e ); public void inspect( YetAnotherElement ); }
  104. 104. ... do you recognize the underlying concept ? interface ElementVisitor{ public void visit( BigElement e ); public void visit( AnotherElement e ); public void visit( YetAnotherElement ); }
  105. 105. Language date.compareTo( otherDate ) < 0 vs. date.isBefore( otherDate )
  106. 106. Codeslicing
  107. 107. Locality
  108. 108. Trust
  109. 109. 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() ) );
  110. 110. 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(); ...}
  111. 111. Liskovsubtype of T, then objects of type T in a if S is a Substitution Principle program may be replaced with objects of type S without altering any of the desirable properties
  112. 112. Open Closed Principle
  113. 113. Principle of least astonishment
  114. 114. Symmetry & balance
  115. 115. ...void writeToFile( Output outout ){ openFile(); writeToFile( output );}
  116. 116. void process{ input(); count++; output();}
  117. 117. One level of abstraction
  118. 118. Dependency Inversion Principle declarative vs Intention Revealing Interfaces imperative Functional Programming Yagni Immutability side effects Expressiveness Domain Driven Design Consistence
  119. 119. If there are three things to keep in mind ...
  120. 120. … its not only developers! developers! developers! ...
  121. 121. … but Empathy! Empathy! Empathy!
  122. 122. Now stop hacking code for machines start writing programs for humans… and the rest will follow ...
  1. Gostou de algum slide específico?

    Recortar slides é uma maneira fácil de colecionar informações para acessar mais tarde.

×