301aa - advanced programming [ap-2017] -...

51
301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini [email protected] Assistant: Lillo GalleBa [email protected] Department of Computer Science, Pisa Academic Year 2017/18 AP-2017-11: Frameworks and Inversion of Control

Upload: vuxuyen

Post on 09-Apr-2018

216 views

Category:

Documents


2 download

TRANSCRIPT

301AA-AdvancedProgramming[AP-2017]

Lecturer:[email protected]:[email protected]

DepartmentofComputerScience,PisaAcademicYear2017/18

AP-2017-11:FrameworksandInversionofControl

FrameworksandInversionofControl

•  Recap:JavaBeansasComponents•  Frameworks,ComponentFrameworksandtheirfeatures

•  FrameworksvsIDEs•  InversionofControlandContainers•  FrameworksvsLibraries•  DecouplingComponents•  DependencyInjecVon•  IoCContainersinSpring

2

Components:arecap

•  Example:JavaBeans•  Contractuallyspecifiedinterfaces:events,methodsandproperVes

•  Explicitcontextdependencies:serializable,constructorwithnoargument

•  Subjecttocomposi?on:connecVontootherbeans–  UsingconnecVonorientedprogramming(eventsourceandlisteners)

3

Aso$warecomponentisaunitofcomposi1onwithcontractuallyspecifiedinterfacesandexplicitcontextdependenciesonly.Aso\warecomponentcanbedeployedindependentlyandissubjecttocomposi1onbythirdparty.ClemensSzyperski,ECOOP1996

TowardsComponentFrameworks•  So$wareFramework:AcollecVonofcommoncodeproviding

genericfunc?onalitythatcanbeselec?velyoverriddenorspecializedbyusercodeprovidingspecificfunc?onality

•  Applica1onFramework:Aso\wareframeworkusedtoimplementthestandardstructureofanapplicaVonforaspecificdevelopmentenvironment

•  Web(Applica1on)Framework:asabove,forWebApplicaVons–  ASP.NETbyMicroso\forwebsites,webapplicaVonsandweb

services–  GWT-GoogleWebToolkit(GWT)–  Rails-WriBeninRuby-Providesdefaultstructuresfordatabases,

webservicesandwebpages.–  Spring- forJava-basedenterprisewebapplicaVons

4

Web Application Frameworks

GUI Toolkits

5

ExamplesofFrameworks

ExamplesofFrameworks

•  Generalso\wareframeworks–  .NET–Windowsplaborm.Provideslanguageinteroperability

– AndroidSDK–SupportsdevelopmentofappsinJava(butdoesnotuseaJVM!)

– Cocoa–Apple’snaVveOOAPIformacOS.IncludesCstandardlibraryandtheObjecVve-CrunVme.

– Eclipse–Cross-plaborm,easilyextensibleIDEwithplugins

ExamplesofFrameworks

•  FrameworksforApplicaVonwithGUI– MFC-Microso\FoundaVonClassLibrary.C++object-orientedlibraryforWindows.

– Gnome–WriBeninC;mainlyforLinux

– Qt-Cross-plaborm;wriBeninC++

ExamplesofFrameworks

•  WebApplicaVonFrameworks[basedonModel-View-ControllerdesignpaBern]– ASP.NETbyMicroso\forwebsites,webapplicaVonsandwebservices

– GWT-GoogleWebToolkit(GWT)– Rails-WriBeninRuby-Providesdefaultstructuresfordatabases,webservicesandwebpages.

ExamplesofFrameworks

•  Concurrency– HadoopMap/Reduce-so\wareframeworkforapplicaVonswhichprocessbigamountsofdatain-parallelonlargeclusters(thousandsofnodes)inafault-tolerantmanner.

• Map:Takesinputdataandconvertsitintoasetoftuples(key/valuepairs).

•  Reduce:TakestheoutputfromMapandcombinesthedatatuplesintoasmallersetoftuples.

FeaturesofFrameworks•  Aframeworkembodiessomeabstractdesign,withmorebehaviorbuiltin.

•  Inordertouseityouneedtoinsertyourbehaviorintovariousplacesintheframeworkeitherbysubclassingorbyplugginginyourownclasses.

•  Theframework’scodethencallsyourcodeatthesepoints.

•  Averygeneralconcept,emphasizinginversionofcontrol:asopposedtolibrariesisthecodeoftheframeworkthatcallsthecode

10

ComponentFrameworks•  Frameworksthatsupportdevelopment,deployment,composiVon

andexecuVonofcomponentsdesignedaccordingtoagivenComponentModel

•  Supportthedevelopmentofindividualcomponents,enforcingthedesignofpreciseinterfaces

•  Supportthecomposi1on/connec1onofcomponentsaccordingtothemechanismsprovidedbytheComponentModel

•  Allowsinstancesofthesecomponentstobe“plugged”intothecomponentframeworkitself

•  Provideprebuiltfunc1onali1es,suchasusefulcomponentsorautomatedassemblyfuncVonsthatautomaVcallyinstanVateandcomposecomponentstoperformcommontasks.

•  ThecomponentframeworkestablishesenvironmentalcondiVonsforthecomponentinstancesandregulatestheinteracVonbetweencomponentinstances.

11

FrameworksvsIDEs

•  Orthogonalconcepts•  AframeworkcanbesupportedbyseveralIDEs

– Eg:SpringsupportedbySpringToolSuite(basedonEclipse),NetBeans,IntelliJIDEA,Eclipse,…

•  AnIDEcansupportseveralframeworks– Eg:NetBeanssupportsJavaBeans,Spring,J2EE,Maven,Hibernate,JavaServerFaces,Struts,Qt,…

•  InteresVngissue:composiVonalapproachtoframeworks

12

FrameworksFeatures•  Consistofpartsthatarefoundinmanyappsofthattype

–  LibrarieswithAPIs(classeswithmethodsetc.)–  Ready-madeextensibleprograms("engines")–  SomeVmesalsotools(e.g.fordevelopment,configuraVon,content)

•  Frameworks,likeso\warelibraries,providereusableabstrac9onsofcodewrappedinawell-definedAPI

•  But:Inversionofcontrol–  unlikeinlibraries,theoverallprogram'sflowofcontrolisnotdictated

bythecaller,butbytheframework •  Helpssolvingrecurringdesignproblems

–  Providingadefaultbehavior–  DictaVnghowtofill-in-the-blanks

•  Non-modifiableframeworkcode–  Extensibility:usuallybyselecVveoverriding

13

Extensibility•  Allframeworkscanbeextendedtocaterforapp-specificfuncVonality.–  AframeworkisintendedtobeextendedtomeettheneedsofaparVcularapplicaVon

•  Commonwaystoextendaframework:–  Extensioniscarriedoutbysub-classing,overridingmethods,andimplemenVnginterfaces

–  Plug-ins:frameworkcanloadcertainextracodeinaspecificformat

– Withintheframeworklanguage:•  Subclassing&overridingmethods•  ImplemenVnginterfaces•  Registeringeventhandlers

14

Twoselectedtopics

Wegiveacloserlooktotwogeneraltopicsrelatedtoframeworks:•  Inversionofcontrol•  Masteringdependenciesamongcomponents

15

InversionofControl(IoC)inGUIs

•  Intext-basedinteracVon,theorderofinteracVonsandofinvocaVonsisdecidedbythethecode.

•  IntheGUI-basedinteracVon,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

•  TheapplicaVonarchitectureiso\enfixed,evenifcustomizable,anddeterminedbytheFramework–  Whenusingaframework,oneusuallyjustimplementsafewcallbackfuncVonsorspecializesafewclasses,andtheninvokesasinglemethodorprocedure.

–  Theframeworkdoestherestoftheworkforyou,invokinganynecessaryclientcallbacksormethodsattheappropriateVmeandplace.

•  Example:Java'sSwingandAWTclasses,NetBeansprojects–  Theyhaveahugeamountofcodetomanagetheuserinterface,andthereisinversionofcontrolbecauseyoustarttheGUIframeworkandthenwaitforittocallyourlisteners

17

InversionofControlTradiVonalProgramExecuVon InversionofControl

TheapphascontrolovertheexecuVonflow,callinglibrarycodewhenitneedsto.

TheframeworkhascontrolovertheexecuVonflow,callingappcodeforapp-specificbehavior.

18

FrameworksvsLibraries•  Frameworksconsistoflargesetsofclasses/interfaces,suitablypackaged

•  Notmuchdifferentfromlibraries•  (Possible)Keyfeature:wideuseofInversionofControl

•  “Framework”someVmesintendedas“well-designedlibrary”

•  “JavaCollecVonFramework”vs“StandardTemplateLibrary”:arethemframeworksorlibraries?

19

20

JavaCollecVonFramework

StandardTemplateLibrary

Components,ContainersandIoC•  O\enFrameworksprovidecontainersfordeployingcomponents

•  AcontainermayprovideatrunVmefuncVonaliVesneededbythecomponentstoexecute

•  Example:EJBcontainersareresponsibleofthepersistentstorageofdataandoftheavailabilityofEJB’sforallauthorizedclients

•  UsingIoC,EJBcontainerscaninvokeonsessionbeansmethodslikeejbRemove,ejbPassivate(storetosecondarystorage),andejbAc?vate(restorefrompassivestate).

•  Spring’sIoCcontainers:arelatedconcept…

21

Looselycoupledsystems:advantagesandtechniques

•  GoodOOSystemsshouldbeorganisedaswebofinteracVngobjects

•  Goal:Highcohesion,lowcoupling•  Advantagesoflowcoupling

– Extensibility– Testability– Reusability

•  WediscussDependencyinjec9onandothertechniquestoachieveit

22NickHines-DependencyInjec?onandInversionofControl-ThoughtWorks,2006

AConcreteExample–ATradeMonitor

23

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 sysmbol) { // Do something with the database } }

limitDao = new LimitDao();

24

TradeMonitor–TheDesignRefactored(1)

•  Introduceinterface/implementaVonseparaVon–  LogicdoesnotdependonDAOanymore.–  Doesthisreallysolvetheproblem?

public class TradeMonitor { private ILimitRepository limitRepository; public TradeMonitor() { limitRepository = new LimitDao(); } public bool TryTrade(string symbol, int amount) {

. . . } }

public interface ILimitRepository { int GetExposure(string symbol); int GetLimit(string symbol); }

limitRepository = new LimitDao();

•  TheconstructorsVllhasastaVcdependencyonDAO

25

•  IntroduceaFactory.Ithastheresponsibilitytocreatetherequiredinstance.

•  TradeMonitordecoupledfromLimitDao•  LimitDaosVllVghtly-coupledalbeittoFactory

public class LimitFactory { public static ILimitRepository GetLimitRepository() { return new LimitDao(); } } public class TradeMonitor { private ILimitRepository 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(staVc)registryfortheLimitDaoyouneed.

•  Thisgivesusextensibility,testability,reusabilitypublic class ServiceLocator{ public static void RegisterService(Type type, object impl) {. . .} public static object GetService(Type type) {. . .} } public class TradeMonitor{ private ILimitRepository limitRepository; public TradeMonitor(){ object o = ServiceLocator.GetService(typeof(ILimitRepository)); limitRepository = o as ILimitRepository; } public bool TryTrade(string symbol, int amount){ . . . } }

27

TradeMonitor–TheDesignRefactored(3)

ServiceLocator–Prosandcons

•  TheServiceLocatorpaBernsucceedsindecouplingtheTradeMonitorfromtheLimitDao

•  Itcanbegeneralizedinseveralways,eg.tocoverdynamiclookup

•  Cons:– Aformofsequencedependenceremains–  Cumbersomesetupintests–  Servicedependsoninfrastructurecode(theServiceLocator)

–  Codeneedstohandlelookupproblems

28

TowardsDependencyInjecVon•  IntheoriginalsituaVon,weaimat

relaxingthecouplingusingsoluVonsbasedonInversionofControl

Q: Which“control”isinverted?A: ThelookupoftheLimitRepositoryinstancefromTradeMonitor

ThepluginiscreatedbyanexternalAssembleranditispassedtoTradeMonitorinsomeway.Thedependencyisinjectedinthemaincomponent.

29

DependencyInjecVon•  Dependencyinjec1onallowsavoidinghard-codeddependencies(strongcoupling)andchangingthem

•  AllowsselecVonamongmulVpleimplementaVonsofagivendependencyinterfaceatrunVme

•  Examples:–  loadpluginsdynamically–  replacemockobjectsintestenvironmentsvs.realobjectsinproducVonenvironments

•  Threeforms:–  SeBerinjecVon–  ConstructorinjecVon–  (Interfaceinjec?on)

30

DependencyinjecVonbasedonseBermethods

•  WhataboutaddingaseZerandletsomethingelseworryaboutcreaVonandresoluVon?

public class TradeMonitor { private ILimitRepository limitRepository; public TradeMonitor() { } public ILimitRepository Limits { set { limitRepository = value;} } public bool TryTrade(string symbol, int amount){ . . . } }

•  Thedependenciesareinjectedfromtheoutside

•  ComponentsarepassiveandarenotconcernedwithlocaVngorcreaVngdependencies

ThisisSeJerInjec9on

•  WidelyusedinSpring

31

DependencyInjecVonbasedonConstructors

•  Whynotjustusetheconstructor?

public class TradeMonitor { private ILimitRepository limitRepository; public TradeMonitor(ILimitRepository limitRepository) { this.limitRepository = limitRepository; } public bool TryTrade(string symbol, int amount){ . . . } }

•  NoseBersfordependentcomponents,(obviously)

•  One-shotiniValisaVon–componentsarealwaysiniValisedcorrectly

•  Alldependenciesareclearlyvisiblefromcode

•  Itisimpossibletocreatecyclicdependencies

ThisisConstructorInjec9on

•  WidelyusedinPicoContainer

32

SoluVonbasedonConstructorInjecVon&TestCase

[TestFixture] public class TradeMonitorTest { [Test] public void MonitorBlocksTradesWhenLimitExceeded() { DynamicMock mockRepository = new DynamicMock(typeof(ILimitRepository)); mockRepository.SetupResult('GetLimit', 1000000, new Type[] { typeof(string) }); mockRepository.SetupResult('GetExposure', 999999, new Type[] { typeof(string) }); TradeMonitor monitor = new TradeMonitor((ILimitRepository)mockRepository.MockInstance); Assert.IsFalse(monitor.TryTrade('MSFT', 1000), 'Monitor should block trade'); } }

public class TradeMonitor { private ILimitRepository repository; public TradeMonitor(ILimitRepository 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

WhichsoluVontouse?•  BothServiceLocatorandDependencyInjec1onprovide

thedesireddecoupling•  Withservicelocator,thedesidedcomponentisobtained

a\errequesttotheLocator•  WithinjecVonthereisnoexplicitrequest:thecomponent

appearsintheapplicaVonclass•  Inversionofcontrolabithardertounderstand•  WithServiceLocatortheapplicaVonsVlldependsonthe

locator•  Itiseasiertofinddependenciesofcomponentif

DependencyInjecVonisused–  CheckconstructorsandseBersvscheckallinvocaVonstolocatorinthesourcecode

34

TowardsIoCContainers•  TherearesVllsomeopenquesVons

– Whocreatesthedependencies?– WhatifweneedsomeiniValisaVoncodethatmustberuna\erdependencieshavebeenset?

– Whathappenswhenwedon’thaveallthecomponents?

•  IoCContainerssolvetheseissues[eg:Spring]– HaveconfiguraVon–o\enexternal–  Createobjects–  EnsurealldependenciesaresaVsfied–  Providelifecyclesupport

35

OtherpossiblesoluVons•  Reflec1oncanbeusedtodeterminedependencies,reducingtheneedforconfigfiles.– Makecomponentsknowntocontainer.–  Containerexaminesconstructorsanddeterminesdependencies.

•  MostIoCcontainerssupportauto-wiring:automaVcwiringbetweenproperVesofabeanandotherbeansbased,eg,onnameortype

•  Auto-wiringprovidesotherbenefits:–  Lesstyping,especiallylongassemblynames.–  StaVctypecheckingbyIDEateditVme.– MoreintuiVvefordeveloper.

36

IoCContainersandFeatures

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

DependencyinjecVoninSpring•  TheobjectsthatformthebackboneofaSpringapplicaVonare

calledbeans•  AbeanisanobjectthatisinstanVated,assembled,andotherwise

managedbyaSpringIoCcontainer(Applica?onContext)•  BeandefiniVoncontainstheinformaVoncalledconfigura1on

metadata,whichisneededforthecontainertoknowthefollowing–  Howtocreateabean–  Bean’slifecycledetails–  Bean’sdependencies

•  TheconfiguraVonmetadatacanbesuppliedtothecontainerinthreepossibleways:–  XMLbasedconfigura1onfile(thestandard)–  Annota1on-basedconfiguraVon–  Java-basedconfiguraVon

38

SpringIoCcontainers•  TheSpringcontainerisatthecoreoftheSpringFramework.•  Thecontainerwillcreatetheobjects,wirethemtogether,

configurethem,andmanagetheircompletelifecyclefromcreaVonVlldestrucVon.

•  TheSpringcontainerusesDependencyInjec1ontomanagethecomponentsthatmakeupanapplicaVon.

•  ThecontainergetsitsinstrucVonsonwhatobjectstoinstanVate,configure,andassemblebyreadingtheconfigura1onmetadataprovided.

•  TheconfiguraVonmetadatacanberepresentedeitherbyXML,JavaannotaVons,orJavacode.

•  Thediagramtotherightrepresentsahigh-levelviewofhowSpringworks.TheSpringIoCcontainermakesuseofJavaPOJOclassesandconfiguraVonmetadatatoproduceafullyconfiguredandexecutablesystemorapplicaVon.

•  QuicklybrowsingtheSpringArchitecture…https://docs.spring.io/spring/docs/3.0.x/reference/overview.html#overview-modules

39

//imports…publicclassMainApp{publicstaVcvoidmain(String[]args){ApplicaVonContextcontext=newClassPathXmlApplicaVonContext("Beans.xml");HelloWorldobj=(HelloWorld)context.getBean("helloWorld");obj.getMessage();}} Themainclass,loadinganApplica1onContext

40

publicclassHelloWorld{ privateStringmessage; publicvoidsetMessage(Stringmessage){ this.message=message; } publicvoidgetMessage(){ System.out.println("YourMessage:"+message); }} Thebean:aPOJO(PlainOldJavaObject)

<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="hBp://www.springframework.org/schema/beans"xmlns:xsi="hBp://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocaVon="hBp://www.springframework.org/schema/beanshBp://www.springframework.org/schema/beans/spring-beans-3.0.xsd”><beanid="helloWorld"class="com.tutorialspoint.HelloWorld"><propertyname="message"value="HelloWorld!"/></bean></beans> TheConfigura1onMetafile(XML)

SeBerInjecVon(performedbytheIoCcontainer)

So\wareFrameworkDesign

•  IntellectualChallengingTask•  Requiresadeepunderstandingoftheproblemdomain

•  Requiresmasteringofso$ware(design)paZerns,OOmethodsandpolymorphisminparVcular

•  Impossibletoaddressinthecourse,butwecanplayabit…

41

AFrameworkforthefamilyofDivideandConqueralgorithms

•  Idea:startfromawell-knowngenericalgorithm•  ApplyknowntechniquesandpaBernstodefineaframeworkforasoMwarefamily

•  Instancesoftheframework,obtainedbystandardextensionmechanism,willbeconcretealgorithmsofthefamily

42

function solve (Problem p) returns Solution { if isSimple(p)! return simplySolve(p);! else!sp[] = decompose(p);!for (i= 0; i < sp.length; i = i+1)! sol[i] = solve(sp[i]);! return combine(sol);!}!

Frozen/HotSpotsandTemplateMethods•  FrozenSpot:common(shared)aspectoftheso\ware

family•  HotSpot:variableaspectofthefamily•  Templatemethod:concretemethodofbaseclass

implemenVngbehaviorcommontoallmembersofthefamily

•  Ahotspotisrepresentedbyagroupofabstracthookmethods.

•  AtemplatemethodcallsahookmethodtoinvokeafuncVonthatisspecifictoonefamilymember.[InversionofControl]

•  Ahotspotisrealizedinaframeworkasahotspotsubsystem.

43

TheUnificaVonPrinciple•  Theunifica9onprincipleusesinheritancetoimplementthe

hotspotsubsystem.•  Boththetemplatemethodsandhookmethodsaredefinedin

thesameabstractbaseclass.•  Thehookmethodsareimplementedinsubclassesofthebase

class.Inthefigurebelow,thehotspotsubsystemfortheunificaVonapproachconsistsoftheabstractbaseclassanditssubclasses.

44

150 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

Fig. 1. Hot spot subsystem.

specific to one family member. Furthermore, we must separate the various common andvariable aspects from each other and consider them independently, one at a time. We usethe terms frozen spot to denote a common (or shared) aspect of the family and hot spot todenote a variable aspect of the family [22].A software framework is a generic application that allows the creation of different

specific applications from a family [21]. It is an abstract design that can be reused within awhole application domain. In a framework, the frozen spots of the family are representedby a set of abstract and concrete base classes that collaborate in some structure. A behaviorthat is common to all members of the family is implemented by a fixed, concrete templatemethod in a base class. A hot spot is represented by a group of abstract hook methods. Atemplate method calls a hook method to invoke a function that is specific to one familymember.A hot spot is realized in a framework as a hot spot subsystem. A hot spot subsystem

typically consists of an abstract base class, concrete subclasses of that base class, andperhaps other related classes [22]. The hook methods of the abstract base class define theinterface to the alternative implementations of the hot spot. The subclasses of the baseclass implement the hook methods appropriately for a particular choice for a hot spot.Fig. 1 shows a UML class diagram of a hot spot subsystem.There are two principles for framework construction—unification and separation [8].

The unification principle uses inheritance to implement the hot spot subsystem. Both thetemplate methods and hook methods are defined in the same abstract base class. The hookmethods are implemented in subclasses of the base class. In Fig. 1, the hot spot subsystemfor the unification approach consists of the abstract base class and its subclasses. Theseparation principle uses delegation to implement the hot spot subsystem. The templatemethods are implemented in a concrete context class; the hook methods are defined ina separate abstract class and implemented in its subclasses. The template methods thusdelegate work to an instance of the subclass that implements the hook methods. In Fig. 1,the hot spot subsystem for the separation approach consists of both the client (context)class and the abstract base class and its subclasses.A framework is a system that is designed with generality and reuse in mind; and

design patterns [9], which are well-established solutions to program design problemsthat commonly occur in practice, are the intellectual tools for achieving the desiredlevel of generality and reuse. Two design patterns, corresponding to the two frameworkconstruction principles, are useful in implementation of the frameworks.

TheSeparaVonPrinciple•  Thesepara9onprincipleusesdelega1ontoimplementthe

hotspotsubsystem.•  Thetemplatemethodsareimplementedinaconcretecontext

class;thehookmethodsaredefinedinaseparateabstractclassandimplementedinitssubclasses.

•  Thetemplatemethodsthusdelegateworktoaninstanceofthesubclassthatimplementsthehookmethods.Inthefigurebelow,thehotspotsubsystemconsistsofboththeclient(context)classandtheabstractbaseclassanditssubclasses.

45

150 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

Fig. 1. Hot spot subsystem.

specific to one family member. Furthermore, we must separate the various common andvariable aspects from each other and consider them independently, one at a time. We usethe terms frozen spot to denote a common (or shared) aspect of the family and hot spot todenote a variable aspect of the family [22].A software framework is a generic application that allows the creation of different

specific applications from a family [21]. It is an abstract design that can be reused within awhole application domain. In a framework, the frozen spots of the family are representedby a set of abstract and concrete base classes that collaborate in some structure. A behaviorthat is common to all members of the family is implemented by a fixed, concrete templatemethod in a base class. A hot spot is represented by a group of abstract hook methods. Atemplate method calls a hook method to invoke a function that is specific to one familymember.A hot spot is realized in a framework as a hot spot subsystem. A hot spot subsystem

typically consists of an abstract base class, concrete subclasses of that base class, andperhaps other related classes [22]. The hook methods of the abstract base class define theinterface to the alternative implementations of the hot spot. The subclasses of the baseclass implement the hook methods appropriately for a particular choice for a hot spot.Fig. 1 shows a UML class diagram of a hot spot subsystem.There are two principles for framework construction—unification and separation [8].

The unification principle uses inheritance to implement the hot spot subsystem. Both thetemplate methods and hook methods are defined in the same abstract base class. The hookmethods are implemented in subclasses of the base class. In Fig. 1, the hot spot subsystemfor the unification approach consists of the abstract base class and its subclasses. Theseparation principle uses delegation to implement the hot spot subsystem. The templatemethods are implemented in a concrete context class; the hook methods are defined ina separate abstract class and implemented in its subclasses. The template methods thusdelegate work to an instance of the subclass that implements the hook methods. In Fig. 1,the hot spot subsystem for the separation approach consists of both the client (context)class and the abstract base class and its subclasses.A framework is a system that is designed with generality and reuse in mind; and

design patterns [9], which are well-established solutions to program design problemsthat commonly occur in practice, are the intellectual tools for achieving the desiredlevel of generality and reuse. Two design patterns, corresponding to the two frameworkconstruction principles, are useful in implementation of the frameworks.

H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169 153

Fig. 3. Template method for divide and conquer.

abstract public class DivConqTemplate{ public final Solution solve(Problem p)

{ Problem[] pp;if (isSimple(p)){ return simplySolve(p); }else { pp = decompose(p); }Solution[] ss = new Solution[pp.length];for(int i=0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return combine(p,ss);

}abstract protected boolean isSimple (Problem p);abstract protected Solution simplySolve (Problem p);abstract protected Problem[] decompose (Problem p);abstract protected Solution combine(Problem p,Solution[] ss);

}

Fig. 4. Template method framework implementation.

as follows:

public interface Problem {};public interface Solution {};

Given the auxiliary types above, we define the abstract Template Method classDivConqTemplate as shown in Fig. 4. We generalize the combine()method to take boththe description of the problem and the subproblem solution array as arguments. The divide

Applyingtheunifica1onprinciple:

UMLdiagramofthesoluVon

46

function solve (Problem p) returns Solution { if isSimple(p)! return simplySolve(p);! else!sp[] = decompose(p);!for (i= 0; i < sp.length; i = i+1)! sol[i] = solve(sp[i]);! return combine(sol);!}!

47

function solve (Problem p) returns Solution { if isSimple(p)! return simplySolve(p);! else!sp[] = decompose(p);!for (i= 0; i < sp.length; i = i+1)! sol[i] = solve(sp[i]);! return combine(sol);!}!

H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169 153

Fig. 3. Template method for divide and conquer.

abstract public class DivConqTemplate{ public final Solution solve(Problem p)

{ Problem[] pp;if (isSimple(p)){ return simplySolve(p); }else { pp = decompose(p); }Solution[] ss = new Solution[pp.length];for(int i=0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return combine(p,ss);

}abstract protected boolean isSimple (Problem p);abstract protected Solution simplySolve (Problem p);abstract protected Problem[] decompose (Problem p);abstract protected Solution combine(Problem p,Solution[] ss);

}

Fig. 4. Template method framework implementation.

as follows:

public interface Problem {};public interface Solution {};

Given the auxiliary types above, we define the abstract Template Method classDivConqTemplate as shown in Fig. 4. We generalize the combine()method to take boththe description of the problem and the subproblem solution array as arguments. The divide

H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169 153

Fig. 3. Template method for divide and conquer.

abstract public class DivConqTemplate{ public final Solution solve(Problem p)

{ Problem[] pp;if (isSimple(p)){ return simplySolve(p); }else { pp = decompose(p); }Solution[] ss = new Solution[pp.length];for(int i=0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return combine(p,ss);

}abstract protected boolean isSimple (Problem p);abstract protected Solution simplySolve (Problem p);abstract protected Problem[] decompose (Problem p);abstract protected Solution combine(Problem p,Solution[] ss);

}

Fig. 4. Template method framework implementation.

as follows:

public interface Problem {};public interface Solution {};

Given the auxiliary types above, we define the abstract Template Method classDivConqTemplate as shown in Fig. 4. We generalize the combine()method to take boththe description of the problem and the subproblem solution array as arguments. The divide

Codeoftheframework(unifica?onprinciple)

48

H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169 155

public class QuickSort extends DivConqTemplate{ protected boolean isSimple (Problem p)

{ return ( ((QuickSortDesc)p).getFirst() >=((QuickSortDesc)p).getLast() );

}protected Solution simplySolve (Problem p){ return (Solution) p ; }protected Problem[] decompose (Problem p){ int first = ((QuickSortDesc)p).getFirst();

int last = ((QuickSortDesc)p).getLast();int[] a = ((QuickSortDesc)p).getArr ();int x = a[first]; // pivot valueint sp = first;for (int i = first + 1; i <= last; i++){ if (a[i] < x) { swap (a, ++sp, i); } }swap (a, first, sp);Problem[] ps = new QuickSortDesc[2];ps[0] = new QuickSortDesc(a,first,sp-1);ps[1] = new QuickSortDesc(a,sp+1,last);return ps;

}protected Solution combine (Problem p, Solution[] ss){ return (Solution) p; }private void swap (int [] a, int first, int last){ int temp = a[first];

a[first] = a[last];a[last] = temp;

}}

Fig. 6. Quicksort application.

3.3. Constructing a framework using separation

As an alternative to the above design, we can use the separation principle and Strategypattern to implement a divide and conquer framework. The UML class diagram for this ap-proach is shown in Fig. 7. The template method is implemented in the (concrete) contextclass DivConqContext as shown in Fig. 8. The hook methods are defined in the (abstract)Strategy class DivConqStrategy as shown in Fig. 9. The context class delegates the hookmethod calls to a reference to the instance of the Strategy class that it stores internally. Notethat the Strategy approach is more flexible than the Template Method approach in that it ispossible to switch Strategy objects dynamically by using the setAlgorithm()method ofthe context class. Constructing an application of the Strategy-based framework for Quick-sort requires that we implement a subclass of the abstract class DivConqStrategy that isquite similar to the QuickSort class used in the unification framework (shown in Fig. 6).The divide and conquer family of algorithms is a simple example that can be used

to illustrate both approaches to framework design. It consists of a set of algorithms thatshould be known to the students. Hence, the application domain should be easy to explain.In the associated project, students can be given the framework and asked to construct

154 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

public class QuickSortDesc implements Problem, Solution{ public QuickSortDesc(int[]arr, int first, int last)

{ this.arr = arr; this.first = first; this.last = last; }public int getFirst () { return first; }public int getLast () { return last; }private int[] arr; // instance dataprivate int first, last;

}

Fig. 5. Quicksort Problem and Solution implementation.

and conquer framework thus consists of the DivConqTemplate class and the Problemand Solution interfaces. We can now consider an application built using this frameworklibrary.

3.2. Building an application of the framework

In using a traditional procedure or class library, a client’s program is in control of thecomputation; it “calls down” to code from the library. However, frameworks usually exhibitan inversion of control. The framework’s code is in control of the computation; its templatemethods “call down” to the client-supplied hook methods. This section illustrates the useof the divide and conquer framework to build a quicksort application.Quicksort is an in-place sort of a sequence of values. The description of a problem

consists of the sequence of values and designators for the beginning and ending elementsof the segment to be sorted. To simplify the presentation, we limit its scope to integerarrays. Therefore, it is sufficient to identify a problem by the array and the beginning andending indices of the unsorted segment. Similarly, a solution can be identified by the arrayand the beginning and ending indices of the sorted segment. This similarity between theProblem and Solution descriptions enables us to use the same object to describe both aproblem and its corresponding solution. Thus, we introduce the class QuickSortDesc todefine the needed descriptor objects as shown in Fig. 5. Given the definitions for base classDivConqTemplate and auxiliary class QuickSortDesc, we can implement the concretesubclass QuickSort as shown in Fig. 6.In a teaching module using this case study, both the framework (i.e., the abstract class)

and the framework application (i.e., the implementation of quicksort) can be presentedto the students so that they can discern the collaborations and relationships among theclasses clearly. However, a clear distinction must be made between the framework andits application. As an exercise, the students can be assigned the task of modifying thequicksort application to handle more general kinds of objects. Other algorithms such asmergesort and binary search should also be assigned as exercises. The amount of workthat each hook method has to do differs from one specific algorithm to another. In thequicksort implementation, most of the work is done in the decompose() method, whichimplements the splitting or pivoting operation of quicksort. In mergesort, however, morework will be done in the combine() operation because it must carry out the merge phaseof the mergesort algorithm.

AnapplicaVonoftheframework:

QuickSort(unifica?onprinciple)

Applyingthesepara1onprinciple:

UMLdiagramofthesoluVon

49

function solve (Problem p) returns Solution { if isSimple(p)! return simplySolve(p);! else!sp[] = decompose(p);!for (i= 0; i < sp.length; i = i+1)! sol[i] = solve(sp[i]);! return combine(sol);!}!

156 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

Fig. 7. Strategy pattern for divide and conquer framework.

public final class DivConqContext{ public DivConqContext (DivConqStrategy dc)

{ this.dc = dc; }public Solution solve (Problem p){ Problem[] pp;

if (dc.isSimple(p)) { return dc.simplySolve(p); }else { pp = dc.decompose(p); }Solution[] ss = new Solution[pp.length];for (int i = 0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return dc.combine(p, ss);

}public void setAlgorithm (DivConqStrategy dc){ this.dc = dc; }private DivConqStrategy dc;

}

Fig. 8. Strategy context class implementation.

abstract public class DivConqStrategy{ abstract public boolean isSimple (Problem p);

abstract public Solution simplySolve (Problem p);abstract public Problem[] decompose (Problem p);abstract public Solution combine(Problem p, Solution[] ss);

}

Fig. 9. Strategy object abstract class.

50

Codeoftheframework(separa?onprinciple)

156 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

Fig. 7. Strategy pattern for divide and conquer framework.

public final class DivConqContext{ public DivConqContext (DivConqStrategy dc)

{ this.dc = dc; }public Solution solve (Problem p){ Problem[] pp;

if (dc.isSimple(p)) { return dc.simplySolve(p); }else { pp = dc.decompose(p); }Solution[] ss = new Solution[pp.length];for (int i = 0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return dc.combine(p, ss);

}public void setAlgorithm (DivConqStrategy dc){ this.dc = dc; }private DivConqStrategy dc;

}

Fig. 8. Strategy context class implementation.

abstract public class DivConqStrategy{ abstract public boolean isSimple (Problem p);

abstract public Solution simplySolve (Problem p);abstract public Problem[] decompose (Problem p);abstract public Solution combine(Problem p, Solution[] ss);

}

Fig. 9. Strategy object abstract class.

156 H.C. Cunningham et al. / Science of Computer Programming 59 (2006) 147–169

Fig. 7. Strategy pattern for divide and conquer framework.

public final class DivConqContext{ public DivConqContext (DivConqStrategy dc)

{ this.dc = dc; }public Solution solve (Problem p){ Problem[] pp;

if (dc.isSimple(p)) { return dc.simplySolve(p); }else { pp = dc.decompose(p); }Solution[] ss = new Solution[pp.length];for (int i = 0; i < pp.length; i++){ ss[i] = solve(pp[i]); }return dc.combine(p, ss);

}public void setAlgorithm (DivConqStrategy dc){ this.dc = dc; }private DivConqStrategy dc;

}

Fig. 8. Strategy context class implementation.

abstract public class DivConqStrategy{ abstract public boolean isSimple (Problem p);

abstract public Solution simplySolve (Problem p);abstract public Problem[] decompose (Problem p);abstract public Solution combine(Problem p, Solution[] ss);

}

Fig. 9. Strategy object abstract class.

Conclusions

•  Frameworksasstate-of-the-artsoluVonsforsupporVngreuseandextensibilityofso\waresoluVons

•  InversionofControl•  SomeVmeslargeamountofgluecode,buto\engeneratedautomaVcally

•  Suggestedreading:WhydoIhateFrameworks?http://discuss.joelonsoftware.com/default.asp?joel.3.219431!

51