principles of software construction: objects, design, and …€¦ · 10-09-2019 ·...
TRANSCRIPT
1 17-214
PrinciplesofSoftwareConstruction: Objects,Design,andConcurrencyPart1:DesigningclassesDesignforreuse:delegationandinheritanceCharlieGarrodChrisTimperley
2 17-214
Administrivia
• Homework1gradedsoon• Readingduetoday:EffectiveJava,Items17and50
– OptionalreadingdueThursday– RequiredreadingduenextTuesday
• Homework2dueThursday11:59p.m.
3 17-214
DesigngoalsforyourHomework1solution?
Functionalcorrectness Adherenceofimplementationtothespecifications
Robustness Abilitytohandleanomalousevents
Flexibility Abilitytoaccommodatechangesinspecifications
Reusability Abilitytobereusedinanotherapplication
Efficiency Satisfactionofspeedandstoragerequirements
Scalability Abilitytoserveasthebasisofalargerversionoftheapplication
Security Levelofconsiderationofapplicationsecurity
Source: Braude, Bernstein, Software Engineering. Wiley 2011
4 17-214
OneHomework1solution…
classDocument{privatefinalStringurl;publicDocument(Stringurl){this.url=url;}publicdoublesimilarityTo(Documentd){…ourText=download(url);…theirText=download(d.url);…ourFreq=computeFrequencies(ourText);…theirFreq=computeFrequencies(theirText);returncosine(ourFreq,theirFreq);}…}
5 17-214
ComparetoanotherHomework1solution…
classDocument{privatefinalStringurl;publicDocument(Stringurl){this.url=url;}publicdoublesimilarityTo(Documentd){…ourText=download(url);…theirText=download(d.url);…ourFreq=computeFreq(ourText);…theirFreq=computeFreq(theirText);returncosine(ourFreq,theirFreq);}…}
classDocument{privatefinal…frequencies;publicDocument(Stringurl){…ourText=download(url);frequencies=computeFrequencies(ourText);}publicdoublesimilarityTo(Documentd){returncosine(frequencies,d.frequencies);}…}
6 17-214
UsingtheDocumentclass
Foreachurl:ConstructanewDocumentForeachpairofDocumentsd1,d2:Computed1.similarityTo(d2)…
• Whatistherunningtimeofthis,fornurls?
7 17-214
LatencyNumbersEveryProgrammerShouldKnowJeffDean,SeniorFellow,Google
PRIMITIVELATENCY:nsusmsL1cachereference0.5Branchmispredict5L2cachereference7Mutexlock/unlock25Mainmemoryreference100Compress1KbyteswithZippy3,0003Send1Kbytesover1Gbpsnetwork10,00010Read4KrandomlyfromSSD*150,000150Read1MBsequentiallyfrommemory250,000250Roundtripwithinsamedatacenter500,000500Read1MBsequentiallyfromSSD*1,000,0001,0001Diskseek10,000,00010,00010Read1MBsequentiallyfromdisk20,000,00020,00020SendpacketCA->Netherlands->CA150,000,000150,000150
8 17-214
Thepoint
• Constantsmatter• Designgoalssometimesclearlysuggestonealternative
9 17-214
KeyconceptsfromlastThursday
10 17-214
KeyconceptsfromlastThursday
• Testing– Continuousintegration,practicaladvice– Coveragemetrics,statementcoverage
• ExceptionsinJava• Behavioralsubtyping
– LiskovSubstitutionPrinciple– Thejava.lang.Objectcontracts
11 17-214
Behavioralsubtyping
• e.g.,Compiler-enforcedrulesinJava:– Subtypescanadd,butnotremovemethods– Concreteclassmustimplementallundefinedmethods– Overridingmethodmustreturnsametypeorsubtype– Overridingmethodmustacceptthesameparametertypes– Overridingmethodmaynotthrowadditionalexceptions
• Alsoappliestospecifiedbehavior.Subtypesmusthave:– Sameorstrongerinvariants– Sameorstrongerpostconditionsforallmethods– Sameorweakerpreconditionsforallmethods
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.
12 17-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;}}
13 17-214
Today
• Designforreuse:delegationandinheritance– Java-specificdetailsforinheritance
• Anexerciseinequality
14 17-214
Recallourearliersortingexample:
staticvoidsort(int[]list,booleanascending){…booleanmustSwap;if(ascending){mustSwap=list[i]>list[j];}else{mustSwap=list[i]<list[j];}…}
interfaceOrder{booleanlessThan(inti,intj);}finalOrderASCENDING=(i,j)->i<j;finalOrderDESCENDING=(i,j)->i>j;staticvoidsort(int[]list,Ordercmp){…booleanmustSwap=cmp.lessThan(list[i],list[j]);…}
Version A:
Version B':
15 17-214
Delegation
• Delegationissimplywhenoneobjectreliesonanotherobjectforsomesubsetofitsfunctionality– e.g.here,theSorterisdelegatingfunctionalitytosomeOrder
• Judiciousdelegationenablescodereuse
interfaceOrder{booleanlessThan(inti,intj);}finalOrderASCENDING=(i,j)->i<j;finalOrderDESCENDING=(i,j)->i>j;staticvoidsort(int[]list,Ordercmp){…booleanmustSwap=cmp.lessThan(list[i],list[j]);…}
16 17-214
Delegation
• Delegationissimplywhenoneobjectreliesonanotherobjectforsomesubsetofitsfunctionality– e.g.here,theSorterisdelegatingfunctionalitytosomeOrder
• Judiciousdelegationenablescodereuse– Sortercanbereusedwitharbitrarysortorders– Orderscanbereusedwitharbitraryclientcodethatneedstocompare
integersinterfaceOrder{booleanlessThan(inti,intj);}finalOrderASCENDING=(i,j)->i<j;finalOrderDESCENDING=(i,j)->i>j;staticvoidsort(int[]list,Ordercmp){…booleanmustSwap=cmp.lessThan(list[i],list[j]);…}
17 17-214
Usingdelegationtoextendfunctionality
• Considerthejava.util.List(excerpted):publicinterfaceList<E>{publicbooleanadd(Ee);publicEremove(intindex);publicvoidclear();…}
• Supposewewantalistthatlogsitsoperationstotheconsole…
18 17-214
Usingdelegationtoextendfunctionality
• Onesolution:publicclassLoggingList<E>implementsList<E>{privatefinalList<E>list;publicLoggingList<E>(List<E>list){this.list=list;}publicbooleanadd(Ee){System.out.println("Adding"+e);returnlist.add(e);}publicEremove(intindex){System.out.println("Removingat"+index);returnlist.remove(index);}…
TheLoggingListiscomposedofaList,anddelegates(thenon-logging)functionalitytothatList
19 17-214
Delegationanddesign
• Smallinterfaceswithclearcontracts• Classestoencapsulatealgorithms,behaviors
– E.g.,theOrder
20 17-214
Today
• Designforreuse:delegationandinheritance– Java-specificdetailsforinheritance
• Anexerciseinequality
21 17-214
Consider:typesofbankaccounts
publicinterfaceCheckingAccount{publiclonggetBalance();publicvoiddeposit(longamount);publicbooleanwithdraw(longamount);publicbooleantransfer(longamount,Account???target);publiclonggetFee();}
publicinterfaceSavingsAccount{publiclonggetBalance();publicvoiddeposit(longamount);publicbooleanwithdraw(longamount);publicbooleantransfer(longamount,Account???target);publicdoublegetInterestRate();}
22 17-214
Interfaceinheritanceforanaccounttypehierarchy
publicinterfaceAccount{publiclonggetBalance();publicvoiddeposit(longamount);publicbooleanwithdraw(longamount);publicbooleantransfer(longamount,Accounttarget);publicvoidmonthlyAdjustment();}
publicinterfaceCheckingAccountextendsAccount{publiclonggetFee();}
publicinterfaceSavingsAccountextendsAccount{publicdoublegetInterestRate();}
publicinterfaceInterestCheckingAccountextendsCheckingAccount,SavingsAccount{}
23 17-214
Thepowerofobject-orientedinterfaces
• Subtypepolymorphism– Differentkindsofobjectscanbetreateduniformlybyclientcode– Eachobjectbehavesaccordingtoitstype
• e.g.,ifyouaddnewkindofaccount,clientcodedoesnotchange:
Iftodayisthelastdayofthemonth:ForeachacctinallAccounts:acct.monthlyAdjustment();
24 17-214
publicabstractclassAbstractAccount implementsAccount{protectedlongbalance=0;publiclonggetBalance(){ returnbalance;}abstractpublicvoidmonthlyAdjustment();//othermethods…
}publicclassCheckingAccountImpl extendsAbstractAccount implementsCheckingAccount{publicvoidmonthlyAdjustment(){ balance-=getFee();}publiclonggetFee(){…}
}
Implementationinheritanceforcodereuse
25 17-214
publicabstractclassAbstractAccount implementsAccount{protectedlongbalance=0;publiclonggetBalance(){ returnbalance;}abstractpublicvoidmonthlyAdjustment();//othermethods…
}publicclassCheckingAccountImpl extendsAbstractAccount implementsCheckingAccount{publicvoidmonthlyAdjustment(){ balance-=getFee();}publiclonggetFee(){…}
}
Implementationinheritanceforcodereuse
protectedelementsarevisibleinsubclasses
anabstractclassismissingtheimplementationofone
ormoremethods
anabstractmethodislefttobe
implementedinasubclass
noneedtodefinegetBalance()–thecodeisinheritedfrom
AbstractAccount
26 17-214
Inheritance:aglimpseatthehierarchy
• ExamplesfromJava– java.lang.Object– Collectionslibrary
27 17-214
JavaCollectionsAPI(excerpt)
Collection
List Set AbstractCollection
AbstractList
LinkedList
Vector
HashSet
AbstractSequentialList
AbstractSet
Cloneable
ArrayList
interfaces
28 17-214
Theabstractjava.util.AbstractList<E>
abstractEget(inti);abstractintsize();booleanset(inti,Ee);//pseudo-abstractbooleanadd(Ee);//pseudo-abstractbooleanremove(Ee);//pseudo-abstractbooleanaddAll(Collection<?extendsE>c);booleanremoveAll(Collection<?>c);booleanretainAll(Collection<?>c);booleancontains(Ee);booleancontainsAll(Collection<?>c);voidclear();booleanisEmpty();Iterator<E>iterator();Object[]toArray()<T>T[]toArray(T[]a);…
29 17-214
Usingjava.util.AbstractList<E>
publicclassReversedList<E>extendsjava.util.AbstractList<E>implementsjava.util.List<E>{privatefinalList<E>list;publicReversedList(List<E>list){this.list=list;}@Overridepublicintsize(){returnlist.size();}@OverridepublicEget(intindex){returnlist.get(size()-index-1);}}
30 17-214
Benefitsofinheritance
• Reuseofcode• Modelingflexibility
31 17-214
Inheritanceandsubtyping
• Inheritanceisforpolymorphismandcodereuse– Writecodeonceandonlyonce– Superclassfeaturesimplicitlyavailablein
subclass
• Subtypingisforpolymorphism– Accessingobjectsthesameway,butgetting
differentbehavior– Subtypeissubstitutableforsupertype
classAextendsB
classAimplementsBclassAextendsB
32 17-214
Typicalrolesforinterfacesandclasses
• Aninterfacedefinesexpectations/commitmentsforclients• Aclassfulfillstheexpectationsofaninterface
– Anabstractclassisaconvenienthybrid– Asubclassspecializesaclass'simplementation
33 17-214
Javadetails:extendedreusewithsuper
publicabstractclassAbstractAccountimplementsAccount{protectedlongbalance=0;publicbooleanwithdraw(longamount){//withdrawsmoneyfromaccount(codenotshown)}
}publicclassExpensiveCheckingAccountImpl extendsAbstractAccountimplementsCheckingAccount{publicbooleanwithdraw(longamount){ balance-=HUGE_ATM_FEE; booleansuccess=super.withdraw(amount) if(!success) balance+=HUGE_ATM_FEE; returnsuccess;}
}
Overrideswithdrawbutalsousesthesuperclasswithdrawmethod
34 17-214
Javadetails:constructorswiththisandsuper
publicclassCheckingAccountImpl extendsAbstractAccountimplementsCheckingAccount{
privatelongfee;
publicCheckingAccountImpl(longinitialBalance,longfee){ super(initialBalance); this.fee=fee;}
publicCheckingAccountImpl(longinitialBalance){ this(initialBalance,500);}/*othermethods…*/} Invokesanother
constructorinthissameclass
Invokesaconstructorofthesuperclass.Mustbethe
firststatementoftheconstructor.
35 17-214
Javadetails:final
• Afinalfield:preventsreassignmenttothefieldafterinitialization
• Afinalmethod:preventsoverridingthemethod• Afinalclass:preventsextendingtheclass
– e.g.,publicfinalclassCheckingAccountImpl{…
36 17-214
Note:type-castinginJava
• Sometimesyouwantadifferenttypethanyouhave– e.g., doublepi=3.14; intindianaPi=(int)pi;
• Usefulifyouknowyouhaveamorespecificsubtype:– e.g., Accountacct=…;CheckingAccountcheckingAcct=(CheckingAccount)acct;longfee=checkingAcct.getFee();– WillgetaClassCastExceptioniftypesareincompatible
• Advice:avoiddowncastingtypes– Never(?)downcastwithinsuperclasstoasubclass
37 17-214
Note:instanceof
• OperatorthattestswhetheranobjectisofagivenclasspublicvoiddoSomething(Accountacct){longadj=0;if(acctinstanceofCheckingAccount){checkingAcct=(CheckingAccount)acct;adj=checkingAcct.getFee();
}elseif(acctinstanceofSavingsAccount){savingsAcct=(SavingsAccount)acct;adj=savingsAcct.getInterest();
}…}
• Advice:avoidinstanceofifpossible– Never(?)useinstanceofinasuperclasstochecktypeagainstsubclass
Warning: This code is bad.
38 17-214
Delegationvs.inheritancesummary
• Inheritancecanimprovemodelingflexibility• Usually,favorcomposition/delegationoverinheritance
– Inheritanceviolatesinformationhiding– Delegationsupportsinformationhiding
• Designanddocumentforinheritance,orprohibitit– Documentrequirementsforoverridinganymethod
39 17-214
Today
• Designforreuse:delegationandinheritance– Java-specificdetailsforinheritance
• Anexerciseinequality
40 17-214
AnObjectmethodexercise
Provideallcodeneededforareasonableequalsmethod:publicfinalclassName{privatefinalStringfirst,last;publicName(Stringfirst,Stringlast){if(first==null||last==null)thrownewNullPointerException();this.first=first;this.last=last;}…}
41 17-214
Whatdoesthefollowingcodeprint?
publicfinalclassName{privatefinalStringfirst,last;publicName(Stringfirst,Stringlast){if(first==null||last==null)thrownewNullPointerException();this.first=first;this.last=last;publicbooleanequals(Nameo){returnfirst.equals(o.first)&&last.equals(o.last);}publicinthashCode(){return31*first.hashCode()+last.hashCode();}publicstaticvoidmain(String[]args){Set<Name>s=newHashSet<>();s.add(newName("Mickey","Mouse"));System.out.println(s.contains(newName("Mickey","Mouse")));}}
(a)true(b)false(c)Itvaries(d)Noneoftheabove
42 17-214
Whatdoesitprint?
(a)true(b)false(c)Itvaries(d)Noneoftheabove TheNameclassoverrideshashCodebutnotequals!ThetwoNameinstancesarethusunequal.
43 17-214
Object.equalshasnotbeenoverridden
publicfinalclassName{privatefinalStringfirst,last;publicName(Stringfirst,Stringlast){if(first==null||last==null)thrownewNullPointerException();this.first=first;this.last=last;publicbooleanequals(Nameo){//Accidentaloverloadingreturnfirst.equals(o.first)&&last.equals(o.last);}publicinthashCode(){return31*first.hashCode()+last.hashCode();}publicstaticvoidmain(String[]args){Set<Name>s=newHashSet<>();s.add(newName("Mickey","Mouse"));System.out.println(s.contains(newName("Mickey","Mouse")));}}
44 17-214
Javadetails:Dynamicmethoddispatch
1. (Compiletime)Determinewhichclasstolookin2. (Compiletime)Determinemethodsignaturetobeexecuted
1. Findallaccessible,applicablemethods2. Selectmostspecificmatchingmethod
45 17-214
Javadetails:Dynamicmethoddispatch
1. (Compiletime)Determinewhichclasstolookin2. (Compiletime)Determinemethodsignaturetobeexecuted
1. Findallaccessible,applicablemethods2. Selectmostspecificmatchingmethod
3. (Runtime)Determinedynamicclassofthereceiver4. (Runtime)Fromdynamicclass,locatemethodtoinvoke
1. Lookformethodwiththesamesignaturefoundinstep22. Otherwisesearchinsuperclassandetc.
46 17-214
Acorrectequalsimplementation
@Overridepublicbooleanequals(Objecto){if(!(oinstanceofName))returnfalse;Namen=(Name)o;returnn.first.equals(first)&&n.last.equals(last);}
47 17-214
Thelesson
• AlwaysoverridehashCodeiffyouoverrideequals• Alwaysuse@Overrideifyouintendtooverrideamethod
– orletyourIDEgeneratethesemethodsforyou…