principles of so3ware construc9on: objects, design, and concurrency part 1: designing...

Post on 03-Aug-2020

4 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1 15-214

SchoolofComputerScience

PrinciplesofSo3wareConstruc9on: Objects,Design,andConcurrencyPart1:DesigningclassesBehavioralsubtypingCharlieGarrod MichaelHilton

2 15-214

Administrivia

•  Homework1duetonight11:59p.m.–  Everyonemustreadandsignourcollabora9onpolicy

•  ReadingdueTuesday:Effec9veJava,Items15and39•  Homework2duenextThursdayat11:59p.m.

3 15-214

KeyconceptsfromTuesday

4 15-214

KeyconceptsfromTuesday

•  Javahasabipar9tetypesystem:primi9vesandobjects•  PowerofOOprogrammingcomesfromdynamicdispatch•  Introduc9ontotes9ng!

–  Testearly,testo3en

5 15-214

Today

•  Func9onalcorrectness,con9nued•  Behavioralsubtyping

–  LiskovSubs9tu9onPrinciple–  Thejava.lang.Objectcontracts

6 15-214

Unittes9ng

•  Testsforsmallunits:methods,classes,subsystems–  Smallesttestablepartofasystem–  Testpartsbeforeassemblingthem–  Intendedtocatchlocalbugs

•  TypicallywriZenbydevelopers•  Manysmall,fast-running,independenttests•  Fewdependenciesonothersystempartsorenvironment

7 15-214

JUnit

•  Apopular,easy-to-use,unit-tes9ngframeworkforJava

8 15-214

AJUnitexample

importorg.junit.Test;importstaticorg.junit.Assert.assertEquals;publicclassAdjacencyListTest{

@TestpublicvoidtestSanityTest(){ Graphg1=newAdjacencyListGraph(10); Vertexs1=newVertex("A"); Vertexs2=newVertex("B"); assertEquals(true,g1.addVertex(s1)); assertEquals(true,g1.addVertex(s2)); assertEquals(true,g1.addEdge(s1,s2)); assertEquals(s2,g1.getNeighbors(s1)[0]);}

@Testpublicvoidtest….

privateinthelperMethod…

}

9 15-214

Selec9ngtestcases

•  Writetestsbasedonthespecifica9on,for:–  Representa9vecases–  Invalidcases–  Boundarycondi9ons

•  Writestresstests–  Automa9callygeneratehugenumbersoftestcases

•  ThinklikeanaZacker•  Othertests:performance,security,systeminterac9ons,…

10 15-214

Ates9ngexample/***computesthesumofthefirstlenvaluesofthearray**@paramarrayarrayofintegersofatleastlengthlen*@paramlennumberofelementstosumup*@returnsumofthefirstlenarrayvalues*@throwsNullPointerExceptionifarrayisnull*@throwsArrayIndexOutOfBoundsExceptioniflen>array.length*@throwsIllegalArgumentExceptioniflen<0*/intpartialSum(intarray[],intlen);

11 15-214

Ates9ngexample/***computesthesumofthefirstlenvaluesofthearray**@paramarrayarrayofintegersofatleastlengthlen*@paramlennumberofelementstosumup*@returnsumofthefirstlenarrayvalues*@throwsNullPointerExceptionifarrayisnull*@throwsArrayIndexOutOfBoundsExceptioniflen>array.length*@throwsIllegalArgumentExceptioniflen<0*/intpartialSum(intarray[],intlen);

•  Testnullarray•  Testlength>array.length•  Testnega9velength•  Testsmallarraysoflength0,1,2•  Testlongarray•  Testlength==array.length•  Stresstestwithrandomly-generatedarraysandlengths

12 15-214

Ates9ngexercise/***Copiesthespecifiedarray,truncatingorpaddingwithzeros*sothecopyhasthespecifiedlength.Forallindicesthatare*validinboththeoriginalarrayandthecopy,thetwoarrayswill*containidenticalvalues.Foranyindicesthatarevalidinthe*copybutnottheoriginal,thecopywillcontain0.*Suchindiceswillexistifandonlyifthespecifiedlength*isgreaterthanthatoftheoriginalarray.**@paramoriginalthearraytobecopied*@paramnewLengththelengthofthecopytobereturned*@returnacopyoftheoriginalarray,truncatedorpaddedwith*zerostoobtainthespecifiedlength*@throwsNegativeArraySizeExceptionifnewLengthisnegative*@throwsNullPointerExceptioniforiginalisnull*/int[]copyOf(int[]original,intnewLength);

13 15-214

Testorganiza9onconven9ons

•  HaveatestclassFooTestforeachpublicclassFoo

•  Separatesourceandtestdirectories–  FooTestandFoointhesamepackage

14 15-214

Testablecode

•  Thinkabouttes9ngwhenwri9ngcode–  Modularityandtestabilitygohandinhand

•  Sametestcanbeusedonallimplementa9onsofaninterface!•  Test-drivendevelopment

–  Wri9ngtestsbeforeyouwritethecode–  TestscanexposeAPIweaknesses

15 15-214

Wri9ngtestablecode//700LOC public boolean foo() { try { synchronized () { if () { } else { } for () { if () { if () { if () { if ()? { if () { for () { } } } } else { if () { for () { if () { } else { } if () { } else { if () { } } if () { if () { if () { for () { } } } } else { } } } else { } } } } }

Source: http://thedailywtf.com/Articles/Coding-Like-the-Tour-de-France.aspx

Unittes9ngasadesignmechanism:•  Codewithlowcomplexity•  Clearinterfacesand

specifica9ons

16 15-214

Runtestsfrequently

•  Runtestsbeforeeverycommit–  Donotcommitcodethatfailsatest

•  Ifen9retestsuitebecomestoolargeandslow:–  Runlocalpackage-leveltests("smoketests“)frequently–  Runalltestsnightly–  Mediumsizedprojectseasilyhave1000softestcases

•  Con9nuousintegra9onserversscaletes9ng

17 15-214

Con9nuousintegra9on:TravisCI

18 15-214

Con9nuousintegra9on:TravisCIbuildhistory

19 15-214

Whenshouldyoustopwri9ngtests?

20 15-214

Whenshouldyoustopwri9ngtests?

•  Whenyourunoutofmoney…•  Whenyourhomeworkisdue…•  Whenyoucan'tthinkofanynewtestcases...•  Thecoverageofatestsuite

–  Tryingtotestallpartsoftheimplementa9on–  Statementcoverage:percentageofprogramstatementsexecuted

•  Compareto:methodcoverage,branchcoverage,pathcoverage

21 15-214

Today

•  Func9onalcorrectness,con9nued•  Behavioralsubtyping

–  LiskovSubs9tu9onPrinciple–  Thejava.lang.Objectcontracts

22 15-214

Theclasshierarchy

•  TherootisObject(allnon-primi9vesareObjects)•  AllclassesexceptObjecthaveoneparentclass

–  Specifiedwithanextendsclause:classGuitarextendsInstrument{...}

–  IfextendsclauseisomiZed,defaultstoObject•  Aclassisaninstanceofallitssuperclasses

Object

ToyInstrument

YoyoGuitar

23 15-214

Behavioralsubtyping

•  e.g.,Compiler-enforcedrulesinJava:–  Subtypescanadd,butnotremovemethods–  Concreteclassmustimplementallundefinedmethods–  Overridingmethodmustreturnsametypeorsubtype–  Overridingmethodmustacceptthesameparametertypes–  Overridingmethodmaynotthrowaddi9onalexcep9ons

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

Barbara Liskov

This is called the Liskov Substitution Principle.

24 15-214

Behavioralsubtyping

•  e.g.,Compiler-enforcedrulesinJava:–  Subtypescanadd,butnotremovemethods–  Concreteclassmustimplementallundefinedmethods–  Overridingmethodmustreturnsametypeorsubtype–  Overridingmethodmustacceptthesameparametertypes–  Overridingmethodmaynotthrowaddi9onalexcep9ons

•  Alsoappliestospecifiedbehavior.Subtypesmusthave:–  Sameorstrongerinvariants–  Sameorstrongerpostcondi9onsforallmethods–  Sameorweakerprecondi9onsforallmethods

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

Barbara Liskov

This is called the Liskov Substitution Principle.

25 15-214

LSPexample:CarisabehavioralsubtypeofVehicle

abstractclassVehicle{intspeed,limit;//@invariantspeed<limit;//@requiresspeed!=0;//@ensuresspeed<\old(speed)abstractvoidbrake();}

classCarextendsVehicle{intfuel;booleanengineOn;//@invariantspeed<limit;//@invariantfuel>=0;//@requiresfuel>0&&!engineOn;//@ensuresengineOn;voidstart(){…}voidaccelerate(){…}//@requiresspeed!=0;//@ensuresspeed<\old(speed)voidbrake(){…}}

Subclass fulfills the same invariants (and additional ones) Overridden method has the same pre and postconditions

26 15-214

LSPexample:HybridisabehavioralsubtypeofCar

classCarextendsVehicle{intfuel;booleanengineOn;//@invariantspeed<limit;//@invariantfuel>=0;//@requiresfuel>0&&!engineOn;//@ensuresengineOn;voidstart(){…}voidaccelerate(){…}//@requiresspeed!=0;//@ensuresspeed<\old(speed)voidbrake(){…}}

classHybridextendsCar{intcharge;//@invariantcharge>=0;//@invariant…//@requires(charge>0||fuel>0)

&&!engineOn;//@ensuresengineOn;voidstart(){…}voidaccelerate(){…}//@requiresspeed!=0;//@ensuresspeed<\old(speed)//@ensurescharge>\old(charge)voidbrake(){…}}Subclass fulfills the same invariants (and additional ones)

Overridden method start has weaker precondition Overridden method brake has stronger postcondition

27 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//methods

}

classSquareextendsRectangle{Square(intw){ super(w,w);}

}

28 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//methods

}

classSquareextendsRectangle{Square(intw){ super(w,w);}

}

(Yes.)

29 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//methods

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

30 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//methods

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

(Yes.)

31 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//@requiresfactor>0;

voidscale(intfactor){ w=w*factor; h=h*factor;}

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

32 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//@requiresfactor>0;

voidscale(intfactor){ w=w*factor; h=h*factor;}

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

(Yes.)

33 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//@requiresfactor>0;

voidscale(intfactor){ w=w*factor; h=h*factor;}

//@requiresneww>0;voidsetWidth(intneww){ w=neww;}

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

34 15-214

IsthisSquareabehavioralsubtypeofRectangle?

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//@requiresfactor>0;

voidscale(intfactor){ w=w*factor; h=h*factor;}

//@requiresneww>0;voidsetWidth(intneww){ w=neww;}

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

}

← Invalidates stronger invariant (h==w) in subclass

classGraphicProgram{voidscaleW(Rectangler,intf){r.setWidth(r.getWidth()*f);}}

(Yes! But the Square is not a square…)

35 15-214

ThisSquareisnotabehavioralsubtypeofRectangle

classRectangle{//@invarianth>0&&w>0;inth,w;Rectangle(inth,intw){ this.h=h;this.w=w;}

//@requiresfactor>0;

voidscale(intfactor){ w=w*factor; h=h*factor;}

//@requiresneww>0;//@ensuresw==neww&&h==old.h;

voidsetWidth(intneww){ w=neww;}

}

classSquareextendsRectangle{//@invarianth>0&&w>0;//@invarianth==w;

Square(intw){ super(w,w);}

//@requiresneww>0;//@ensuresw==neww&&h==neww;@OverridevoidsetWidth(intneww){w=neww;h=neww;}}

36 15-214

Today

•  Func9onalcorrectness,con9nued•  Behavioralsubtyping

–  LiskovSubs9tu9onPrinciple–  Thejava.lang.Objectcontracts

37 15-214

MethodscommontoallObjects

•  equals:returnstrueifthetwoobjectsare“equal”•  hashCode:returnsanintthatmustbeequalforequalobjects,

andislikelytodifferforunequalobjects•  toString:returnsaprintablestringrepresenta9on

38 15-214

Thebuilt-injava.lang.Objectimplementa9ons

•  Provideiden9tyseman9cs:–  equals(Objecto):returnstrueiforeferstothisobject–  hashCode():returnsanear-randomintthatneverchanges–  toString():returnsastringconsis9ngofthetypeandhashcode

•  Forexample:java.lang.Object@659e0bfd

39 15-214

ThetoString()specifica9on

•  Returnsaconcise,butinforma9vetextualrepresenta9on•  Advice:AlwaysoverridetoString(),e.g.:

finalclassPhoneNumber{privatefinalshortareaCode;privatefinalshortprefix;privatefinalshortlineNumber;...@OverridepublicStringtoString(){returnString.format("(%03d)%03d-%04d",areaCode,prefix,lineNumber);}}Numberjenny=...;System.out.println(jenny);Prints:(707)867-5309

40 15-214

Theequals(Object)specifica9on

•  Mustdefineanequivalencerela9on:–  Reflexive:Foreveryobjectx,x.equals(x)isalwaystrue–  Symmetric:Ifx.equals(y),theny.equals(x)–  Transi9ve:Ifx.equals(y)andy.equals(z),thenx.equals(z)

•  Consistent:Equalobjectsstayequal,unlessmutated•  "Non-null":x.equals(null)isalwaysfalse

41 15-214

Anequals(Object)example

publicfinalclassPhoneNumber{privatefinalshortareaCode;privatefinalshortprefix;privatefinalshortlineNumber;@Overridepublicbooleanequals(Objecto){if(!(oinstanceofPhoneNumber))//Doesnullcheckreturnfalse;PhoneNumberpn=(PhoneNumber)o;returnpn.lineNumber==lineNumber&&pn.prefix==prefix&&pn.areaCode==areaCode;}...}

42 15-214

ThehashCode()specifica9on

•  Equalobjectsmusthaveequalhashcodes–  IfyouoverrideequalsyoumustoverridehashCode

•  Unequalobjectsshouldusuallyhavedifferenthashcodes–  Takeallvaluefieldsintoaccountwhenconstruc9ngit

•  Hashcodemustnotchangeunlessobjectismutated

43 15-214

AhashCode()example

publicfinalclassPhoneNumber{privatefinalshortareaCode;privatefinalshortprefix;privatefinalshortlineNumber;@OverridepublicinthashCode(){intresult=17;//Nonzeroisgoodresult=31*result+areaCode;//Constantmustbeoddresult=31*result+prefix;//""""result=31*result+lineNumber;//""""returnresult;}...}

44 15-214

Summary

•  Pleasecompletethecoursereadingassignments•  Testearly,testo3en!•  Subtypesmustfulfillbehavioralcontracts•  AlwaysoverridehashCodeifyouoverrideequals•  Alwaysuse@Overrideifyouintendtooverrideamethod

–  OrletyourIDEgeneratethesemethodsforyou…

top related