301aa - advanced programmingpages.di.unipi.it/corradini/didattica/ap-18/slides/ap-2018-11.pdf ·...
TRANSCRIPT
301AA-AdvancedProgramming
Lecturer:AndreaCorradini [email protected]
h;p://pages.di.unipi.it/corradini/
Coursepages:h;p://pages.di.unipi.it/corradini/Dida@ca/AP-18/
AP-2018-11:FrameworksandInversionofControl
FrameworksandInversionofControl
• Recap:JavaBeansasComponents• Frameworks,ComponentFrameworksandtheirfeatures
• FrameworksvsIDEs• InversionofControlandContainers• FrameworksvsLibraries• DecouplingComponents• DependencyInjecPon• IoCContainersinSpring
2
Components:arecap
• Examples:JavaBeans,CLRAssemblies• Contractuallyspecifiedinterfaces:events,methodsandproperPes
• Explicitcontextdependencies:serializable,constructorwithnoargument
• Subjecttocomposi?on:connecPontootherbeans– UsingconnecPonorientedprogramming(eventsourceandlisteners/delegates)
3
Aso,warecomponentisaunitofcomposi4onwithcontractuallyspecifiedinterfacesandexplicitcontextdependenciesonly.AsoXwarecomponentcanbedeployedindependentlyandissubjecttocomposi4onbythirdparty.ClemensSzyperski,ECOOP1996
TowardsComponentFrameworks
• So,wareFramework:AcollecPonofcommoncodeprovidinggenericfunc?onalitythatcanbeselec?velyoverriddenorspecializedbyusercodeprovidingspecificfunc?onality
• Applica4onFramework:AsoXwareframeworkusedtoimplementthestandardstructureofanapplicaPonforaspecificdevelopmentenvironment.
• Examples:– GUIFrameworks– WebFrameworks– ConcurrencyFrameworks
4
Examples:GeneralSoXwareFrameworks
– .NET–Windowspla^orm.Provideslanguageinteroperability
– AndroidSDK–SupportsdevelopmentofappsinJava(butdoesnotuseaJVM!)
– Cocoa–Apple’snaPveOOAPIformacOS.IncludesCstandardlibraryandtheObjecPve-CrunPme.
– Eclipse–Cross-pla^orm,easilyextensibleIDEwithplugins
6
Examples:GUIFrameworks
• FrameworksforApplicaPonwithGUI– MFC-MicrosoXFoundaPonClassLibrary.C++object-orientedlibraryforWindows.
– Gnome–Wri;eninC;mainlyforLinux
– Qt-Cross-pla^orm;wri;eninC++
7
Examples:WebFrameworks
• WebApplicaPonFrameworks[basedonModel-View-Controllerdesignpa;ern]– ASP.NETbyMicrosoXforwebsites,webapplicaPonsandwebservices
– GWT-GoogleWebToolkit(GWT)– Rails-Wri;eninRuby-Providesdefaultstructuresfordatabases,webservicesandwebpages.
– Spring- forJava-basedenterprisewebapplicaPons– Flask–micro-frameworkinPython,highlyextensible(authenPcaPon,validaPon,ORmapper…asextensions)
https://en.wikipedia.org/wiki/Comparison_of_web_frameworks!
ExamplesofFrameworks
• Concurrency– HadoopMap/Reduce-soXwareframeworkforapplicaPonswhichprocessbigamountsofdatain-parallelonlargeclusters(thousandsofnodes)inafault-tolerantmanner.
• Map:Takesinputdataandconvertsitintoasetoftuples(key/valuepairs).
• Reduce:TakestheoutputfromMapandcombinesthedatatuplesintoasmallersetoftuples.
9
FeaturesofFrameworks
• Aframeworkembodiessomeabstractdesign,withmorebehaviorbuiltin.
• Inordertouseityouneedtoinsertyourbehaviorintovariousplacesintheframeworkeitherbysubclassingorbyplugginginyourownclasses.
• Theframework’scodethencallsyourcodeatthesepoints.
• Averygeneralconcept,emphasizinginversionofcontrol:asopposedtolibrariesisthecodeoftheframeworkthatcallsthecode
10
ComponentFrameworks• Frameworksthatsupportdevelopment,deployment,composiPon
andexecuPonofcomponentsdesignedaccordingtoagivenComponentModel
• Supportthedevelopmentofindividualcomponents,enforcingthedesignofpreciseinterfaces
• Supportthecomposi4on/connec4onofcomponentsaccordingtothemechanismsprovidedbytheComponentModel
• Allowsinstancesofthesecomponentstobe“plugged”intothecomponentframeworkitself
• Provideprebuiltfunc4onali4es,suchasusefulcomponentsorautomatedassemblyfuncPonsthatautomaPcallyinstanPateandcomposecomponentstoperformcommontasks.
• Thecomponentframeworkestablishesenvironmentalcondi4onsforthecomponentinstancesandregulatestheinterac4onbetweencomponentinstances.
11
FrameworksvsIntegratedDevelopmentEnvironments(IDEs)
• Orthogonalconcepts• AframeworkcanbesupportedbyseveralIDEs
– Eg:SpringsupportedbySpringToolSuite(basedonEclipse),NetBeans,IntelliJIDEA,Eclipse,…
• AnIDEcansupportseveralframeworks– Eg:NetBeanssupportsJavaBeans,Spring,J2EE,Maven,Hibernate,JavaServerFaces,Struts,Qt,…
12
FrameworksFeatures• Consistofpartsthatarefoundinmanyappsofthattype
– LibrarieswithAPIs(classeswithmethodsetc.)– Ready-madeextensibleprograms("engines")– SomePmesalsotools(e.g.fordevelopment,configuraPon,content)
• Frameworks,likesoXwarelibraries,providereusableabstrac>onsofcodewrappedinawell-definedAPI
• But:Inversionofcontrol– unlikeinlibraries,theoverallprogram'sflowofcontrolisnotdictated
bythecaller,butbytheframework • Helpssolvingrecurringdesignproblems
– Providingadefaultbehavior– DictaPnghowtofill-in-the-blanks
• Non-modifiableframeworkcode– Extensibility:usuallybyselecPveoverriding
13
Extensibility• Allframeworkscanbeextendedtocaterforapp-specificfuncPonality.– AframeworkisintendedtobeextendedtomeettheneedsofaparPcularapplicaPon
• Commonwaystoextendaframework:– Extensionwithintheframeworklanguage:
• Subclassing&overridingmethods• ImplemenPnginterfaces• Registeringeventhandlers
– Plug-ins:frameworkcanloadcertainextracodeinaspecificformat
14
Twoselectedtopics
Wegiveacloserlooktotwogeneraltopicsrelatedtoframeworks:• Inversionofcontrol• Masteringdependenciesamongcomponents
15
InversionofControl(IoC)inGUIs
• Intext-basedinteracPon,theorderofinteracPonsandofinvocaPonsisdecidedbythethecode.
• IntheGUI-basedinteracPon,theGUIloopdecideswhentoinvokethemethods,basedontheorderofevents
• AlsoknownastheHollywoodPrinciple–“Don'tcallus,we'llcallyou”.
16
#rubyputs'Whatisyourname?'name=getsprocess_name(name)puts'Whatisyourquest?'quest=getsprocess_quest(quest) TEXT
require'tk'root=TkRoot.new()name_label=TkLabel.new(){text"WhatisYourName?"}name_label.packname=TkEntry.new(root).packname.bind("FocusOut"){process_name(name)}quest_label=TkLabel.new(){text"WhatisYourQuest?"}quest_label.packquest=TkEntry.new(root).packquest.bind("FocusOut"){process_quest(quest)}Tk.mainloop() GUI
https://martinfowler.com/bliki/InversionOfControl.html!
InversionofControlinFrameworks
• WithFrameworkstheInversionofControlbecomesdominant
• TheapplicaPonarchitectureisoXenfixed,evenifcustomizable,anddeterminedbytheFramework– Whenusingaframework,oneusuallyjustimplementsafewcallbackfuncPonsorspecializesafewclasses,andtheninvokesasinglemethodorprocedure.
– Theframeworkdoestherestoftheworkforyou,invokinganynecessaryclientcallbacksormethodsattheappropriatePmeandplace.
• Example:Java'sSwingandAWTclasses,NetBeansprojects– Theyhaveahugeamountofcodetomanagetheuserinterface,andthereisinversionofcontrolbecauseyoustarttheGUIframeworkandthenwaitforittocallyourlisteners
17
InversionofControlTradiPonalProgramExecuPon InversionofControl
TheapphascontrolovertheexecuPonflow,callinglibrarycodewhenitneedsto.
TheframeworkhascontrolovertheexecuPonflow,callingappcodeforapp-specificbehavior.
18
FrameworksvsLibraries• Frameworksconsistoflargesetsofclasses/interfaces,suitablypackaged
• Notmuchdifferentfromlibraries• (Possible)Keyfeature:wideuseofInversionofControl
• “Framework”somePmesintendedas“well-designedlibrary”
• “JavaCollecPonFramework”vs“StandardTemplateLibrary”:arethemframeworksorlibraries?
19
Components,ContainersandIoC• OXenFrameworksprovidecontainersfordeployingcomponents
• AcontainermayprovideatrunPmefuncPonaliPesneededbythecomponentstoexecute
• Example:EJBcontainersareresponsibleofthepersistentstorageofdataandoftheavailabilityofEJB’sforallauthorizedclients
• UsingIoC,EJBcontainerscaninvokeonsessionbeansmethodslikeejbRemove,ejbPassivate(storetosecondarystorage),andejbAc?vate(restorefrompassivestate).
• Spring’sIoCcontainers:arelatedconcept…
21
Looselycoupledsystems:advantagesandtechniques
• GoodOOSystemsshouldbeorganisedaswebofinteracPngobjects
• Goal:Highcohesion,lowcoupling• Advantagesoflowcoupling
– Extensibility– Testability– Reusability
• WediscussDependencyinjec>onandothertechniquestoachieveit
22NickHines-DependencyInjec?onandInversionofControl-ThoughtWorks,2006
TradeMonitor–Thedesign
• TradeMonitoriscoupledtoLimitDao[DataAccessObject]–thisisnotgood!– Extensibility–whatifwereplacethedatabasewithadistributedcache?– Testability–wheredothelimitsfortestcomefrom?– Reusability–logicisfairlygeneric...
public class TradeMonitor { private LimitDao limitDao; public TradeMonitor() { limitDao = new LimitDao(); } public bool TryTrade(string symbol, int amount) { int limit = limitDao.GetLimit(symbol); int exposure = limitDao.GetExposure(symbol); return (exposure + amount > limit) ? false : true; } }
public class LimitDao { public int GetExposure(string symbol) { // Do something with the database } public int GetLimit(string symbol) { // Do something with the database } }
limitDao = new LimitDao();
24
TradeMonitor–TheDesignRefactored(1)
• Introduceinterface/implementaPonseparaPon– LogicdoesnotdependonDAOanymore.– Doesthisreallysolvetheproblem?
public class TradeMonitor { private LimitRepository limitRepository; public TradeMonitor() { limitRepository = new LimitDao(); } public bool TryTrade(string symbol, int amount) {
. . . } }
public interface LimitRepository { int GetExposure(string symbol); int GetLimit(string symbol); }
limitRepository = new LimitDao();
• TheconstructorsPllhasastaPcdependencyonDAO
25
• IntroduceaFactory.Ithastheresponsibilitytocreatetherequiredinstance.
• TradeMonitordecoupledfromLimitDao• LimitDaosPllPghtly-coupledalbeittoFactory
public class LimitFactory { public static LimitRepository GetLimitRepository() { return new LimitDao(); } } public class TradeMonitor { private LimitRepository limitRepository; public TradeMonitor() { limitRepository = LimitFactory.GetLimitRepository(); } public bool TryTrade(string symbol, int amount) { . . . } }
LimitFactory
TradeMonitor
<<interface>>LimitRepository
LimitDao
<<creates>>
return new LimitDao();
26
TradeMonitor–TheDesignRefactored(2)
• IntroduceaServiceLocator.Thisobjectactsasa(staPc)registryfortheLimitDaoyouneed.
• Thisgivesusextensibility,testability,reusabilitypublic class ServiceLocator{ public static void RegisterService(Type type, object impl) {. . .} public static object GetService(Type type) {. . .} } public class TradeMonitor{ private LimitRepository limitRepository; public TradeMonitor(){ object o = ServiceLocator.GetService(typeof(LimitRepository)); limitRepository = (LimitRepository) o; } public bool TryTrade(string symbol, int amount){ . . . } }
27
TradeMonitor–TheDesignRefactored(3)
ServiceLocator–Prosandcons
• TheServiceLocatorpa;ernsucceedsindecouplingtheTradeMonitorfromtheLimitDao
• Itcanbegeneralizedinseveralways,eg.tocoverdynamiclookup
• Cons:– Aformofsequencedependenceremains– Cumbersomesetupintests– Servicedependsoninfrastructurecode(theServiceLocator)
– Codeneedstohandlelookupproblems
28
TowardsDependencyInjecPon• IntheoriginalsituaPon,weaimat
relaxingthecouplingusingsoluPonsbasedonInversionofControl
Q: Which“control”isinverted?A: ThelookupoftheLimitRepositoryinstancefromTradeMonitor
ThepluginiscreatedbyanexternalAssembleranditispassedtoTradeMonitorinsomeway.Thedependencyisinjectedinthemaincomponent.
29
DependencyInjecPon• Dependencyinjec4onallowsavoidinghard-codeddependencies(strongcoupling)andchangingthem
• AllowsselecPonamongmulPpleimplementaPonsofagivendependencyinterfaceatrunPme
• Examples:– loadpluginsdynamically– replacemockobjectsintestenvironmentsvs.realobjectsinproducPonenvironments
• Threeforms:– Se;erinjecPon– ConstructorinjecPon– (Interfaceinjec?on)
30
DependencyinjecPonbasedonse;ermethods
• Idea:addaseYer,andletsomethingelseworryaboutcreaPonandresoluPon.
public class TradeMonitor { private LimitRepository limitRepository; public TradeMonitor() { } public LimitRepository Limits { set { limitRepository = value;} } public bool TryTrade(string symbol, int amount){ . . . } }
• Thedependenciesareinjectedfromtheoutside
• ComponentsarepassiveandarenotconcernedwithlocaPngorcreaPngdependencies
ThisisSeKerInjec>on
• WidelyusedinSpring
31
DependencyInjecPonbasedonConstructors
• Whynotjustusetheconstructor?
public class TradeMonitor { private LimitRepository limitRepository; public TradeMonitor(LimitRepository limitRepository) { this.limitRepository = limitRepository; } public bool TryTrade(string symbol, int amount){ . . . } }
• Nose;ersfordependentcomponents,(obviously)
• One-shotiniPalisaPon–componentsarealwaysiniPalisedcorrectly
• Alldependenciesareclearlyvisiblefromcode
• Itisimpossibletocreatecyclicdependencies
ThisisConstructorInjec>on
• WidelyusedinPicoContainer
32
ExploiPngConstructorInjecPonforTesPng
[TestFixture] public class TradeMonitorTest { [Test] public void MonitorBlocksTradesWhenLimitExceeded() { DynamicMock mockRepository = new DynamicMock(typeof(LimitRepository)); mockRepository.SetupResult('GetLimit', 1000000, new Type[] { typeof(string) }); mockRepository.SetupResult('GetExposure', 999999, new Type[] { typeof(string) }); TradeMonitor monitor = new TradeMonitor((LimitRepository)mockRepository.MockInstance); Assert.IsFalse(monitor.TryTrade('MSFT', 1000), 'Monitor should block trade'); } }
public class TradeMonitor { private LimitRepository repository; public TradeMonitor(LimitRepository repository) { this.repository = repository; } public bool TryTrade(string symbol, int amount) { int limit = repository.GetLimit(symbol); int exposure = repository.GetExposure(symbol); return ((amount + exposure) <= limit); } }
33
WhichsoluPontouse?• BothServiceLocatorandDependencyInjec4onprovide
thedesireddecoupling• Withservicelocator,thedesiredcomponentisobtained
aXerrequestbytheTradeMonitortotheLocator:noIoC• WithdependencyinjecPonthereisnoexplicitrequest:the
componentappearsintheapplicaPonclass• Inversionofcontrolabithardertounderstand• WithServiceLocatortheapplicaPonsPlldependsonthe
locator• Itiseasiertofinddependenciesofcomponentif
DependencyInjecPonisused– Checkconstructorsandse;ersvscheckallinvocaPonstolocatorinthesourcecode
34
TowardsIoCContainers• TherearesPllsomeopenquesPons
– Whocreatesthedependencies?– WhatifweneedsomeiniPalisaPoncodethatmustberunaXerdependencieshavebeenset?
– Whathappenswhenwedon’thaveallthecomponents?
• IoCContainerssolvetheseissues[eg:Spring]– HaveconfiguraPon–oXenexternal– Createobjects– EnsurealldependenciesaresaPsfied– Providelifecyclesupport
35
OtherpossiblesoluPons• Reflec4oncanbeusedtodeterminedependencies,reducingtheneedforconfigfiles.– Makecomponentsknowntocontainer.– Containerexaminesconstructorsanddeterminesdependencies.
• MostIoCcontainerssupportauto-wiring:automaPcwiringbetweenproperPesofabeanandotherbeansbased,eg,onnameortype
• Auto-wiringprovidesotherbenefits:– Lesstyping.– StaPctypecheckingbyIDEateditPme.– MoreintuiPvefordeveloper.
36
SomeIoCContainersandtheirFeatures
Container Setter DI
Ctor DI
External config
Code config
Auto-wiring
Lifecycle support`
Url
System.ComponentModel a a Part of .Net framework
PicoContainer.Net a a a a a http://picocontainer.orgWindsor a a a ? a http://www.castleproject.orgStructureMap a a a P a http://sourceforge.net/projects/structuremapSpring.Net a a a ? a a http://www.springframework.net/ObjectBuilder a a a a ?? a http://msdn.microsoft.com
?? = More investigation
? = Setter based DI required for primitive dependenciesP = Partial still requires configuration to point to assemblies to scan
37
DependencyinjecPoninSpring• TheobjectsthatformthebackboneofaSpringapplicaPonare
calledbeans• AbeanisanobjectthatisinstanPated,assembled,andotherwise
managedbyaSpringIoCcontainer(Applica?onContext)• BeandefiniPoncontainstheinformaPoncalledconfigura4on
metadata,whichisneededforthecontainertoknowthefollowing– Howtocreateabean– Bean’slifecycledetails– Bean’sdependencies
• TheconfiguraPonmetadatacanbesuppliedtothecontainerinthreepossibleways:– XMLbasedconfigura4onfile(thestandard)– Annota4on-basedconfiguraPon– Java-basedconfiguraPon
38
SpringIoCcontainers• TheSpringcontainerisatthecoreoftheSpring
Framework.• Thecontainerwillcreatetheobjects,wirethemtogether,
configurethem,andmanagetheircompletelifecyclefromcreaPonPlldestrucPon.
• TheSpringcontainerusesDependencyInjec4ontomanagethecomponentsthatmakeupanapplicaPon.
• ThecontainergetsitsinstrucPonsonwhatobjectstoinstanPate,configure,andassemblebyreadingtheconfigura4onmetadataprovided.
• Thediagramtotherightrepresentsahigh-levelviewofhowSpringworks.TheSpringIoCcontainermakesuseofJavaPOJOclassesandconfiguraPonmetadatatoproduceafullyconfiguredandexecutablesystemorapplicaPon.
• QuicklybrowsingtheSpringArchitecture…https://docs.spring.io/spring/docs/3.0.x/reference/overview.html#overview-modules
39
//imports…publicclassMainApp{publicstaPcvoidmain(String[]args){ApplicaPonContextcontext=newClassPathXmlApplicaPonContext("Beans.xml");HelloWorldobj=(HelloWorld)context.getBean("helloWorld");obj.getMessage();}} Themainclass,loadinganApplica4onContext
40
publicclassHelloWorld{ privateStringmessage; publicvoidsetMessage(Stringmessage){ this.message=message; } publicvoidgetMessage(){ System.out.println("YourMessage:"+message); }} Thebean:aPOJO(PlainOldJavaObject)
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="h;p://www.springframework.org/schema/beans"xmlns:xsi="h;p://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocaPon="h;p://www.springframework.org/schema/beansh;p://www.springframework.org/schema/beans/spring-beans-3.0.xsd”><beanid="helloWorld"class="com.tutorialspoint.HelloWorld"><propertyname="message"value="HelloWorld!"/></bean></beans> TheConfigura4onMetafile(XML)
Se;erInjecPon(performedbytheIoCcontainer)