Template Method Intermesso


onsdag 1. februar 2012 OO Patterns

tm_intermessoDet blir et kort opphold i den oppsatte sendeplanen for å gjøre plass til en litt grundigere forklaring av hva det er vi snakker om her.

Da jeg presenterte min "funksjonelle" løsning i del 2 av Template Method-serien min dukket det opp et spørsmål: Er ikke dette egentlig Strategy Pattern? Jeg svarte at det fortsatt var Template Method, men at det nå lå bedre til rette også for ulike strategier.

Lars-Petter fulgte opp på mail med å si at han mener "..forskjellen på TM og Strategy nettopp er om du bruker arv eller ikke. Det er i hvertfall det jeg kan lese ut av mine bøker, GoF inkudert."

Jeg setter stor pris på spørsmålet, og vil forsøke å forklare mitt ståsted...

Forskjellen på Template Method og Strategy

Strategy Pattern og Template Method Pattern er på mange måter ganske like, men målet med dem er forskjellig. Strategy brukes for å tillate ulike implementasjoner av en algoritme eller operasjon, som så kan velges dynamisk i runtime. Målet med Template Method er ikke å tillate adferd å bli implementert på ulike måter, men å forsikre at en bestemt adferd/algoritme blir implementert på én måte.

Med andre ord: Mens Strategy fokuserer på å tillate variasjon, fokuserer Template Method på å forsikre konsistent adferd. (kilde)

Kanskje noen grafiske representasjoner kan hjelpe på å se det bedre. Her ser du en representasjon av en typisk Template Method Pattern implementasjon:

templatemethod_graphical

Den abstrakte klassen eksisterer for å forsikre én bestemt algoritme, men åpner for ulike implementasjoner av enkelte detaljer. De to konkrete klassene representerer ulike implementasjoner av disse detaljene. Sammenlign dette med følgende representasjon av strategy:

strategy_graphical

Strategy definerer et grensesnitt – et sett med steg om du vil. Disse settene er utbyttbare, og kan brukes om hverandre av ulike algoritmer. Målet er derimot ikke å sikre en bestemt algoritme i seg selv – Strategy Pattern begynner svært ofte som et rent interface uten noe funksjonalitet. Strategy dreier seg ofte mer om å gi forventninger om et bestemt resultat, men ikke hvordan det implementeres (tenk f.eks. ulike strategier for sortering).

Så hva var det da jeg lagde i del 2 av min Template Method-serie? Vel, se på denne representasjonen:

functionaltemplate_graphical

Jeg implementerte en konkret klasse som definerte en fast allgoritme, men hvor enkelte steg var utbyttbare. Motivasjonen min er altså den samme som for Template Method pattern. Forskjellen er at min implementasjon, siden den ikke baserer seg på arv, ikke krever at hvert av stegene kommer fra samme kilde.

Template Method kan derimot danne grunnlaget for ulike strategier, og det var det jeg snakket om da jeg hevdet at den klassiske implementasjonen var regid, mens min var mer fleksibel. Med min kunne jeg enklere kombinere ulike byggestener til nye strategier basert på templaten. Så bloggserien handlet på en måte om Strategy også.

Min løsning er altså Template Method Pattern "i ånden". Spørsmålet er da om jeg får lov til å kalle det det når jeg ikke implementerer det slik som The Gang of Four gjorde!? For å svare på det må jeg utdype mitt syn på konseptet design patterns...

Hva er egentlig Design Patterns?

Mange ser på design patterns som implementasjons-oppskrifter. WikiPedia legger også vekt på dette. Der står det blant annet:

"Design patterns are composed of several sections. Of particular interest are the Structure, Participants, and Collaboration sections. These sections describe a design motif: a prototypical micro-architecture that developers copy and adapt to their particular designs to solve the recurrent problem described by the design pattern."

Jeg ser derimot på design patterns først og fremts som problembeskrivelser. De delene av patterns-beskrivelsen jeg legger mest vekt på er Intent, Motivation (Forces) og Consequences. Som regel (ok da, omtrent ALLTID) beskrives mønstrene i kontekst av objektorienterte språk, men motivasjonen eller utfordringene bak dem er ikke begrenset til det domenet, og lærdommen bak dem strekker seg lengre – selv om både dynamiske språk og funksjonelle språk gjør mange av problemene trivielle i forhold til hvordan de må løses i språk som C++ eller Java.

Design Patters kan altså (ifølge meg) diskuteres uavhengig av implementasjonsteknikk – løsningene er (kun) eksempler, og må tilpasses. Mønstrene er kommunikasjonsredskaper som fungerer på tvers av programmeringsparadigmene. De oppfattes i alle fall slik av meg, som startet med statisk objektorientering, for så utvide horisonten flere år senere.

Jeg finner flere som støtter mitt syn på dette. Budskapet i dette foredraget om "funksjonelle design patterns" som et eksempel – presentert av PhD in Computer Science Aino Corry, som har gjort en Master Thesis om Design Patterns - er i tråd med min oppfatning.

Konklusjon

Jeg oppfatter altså spørsmålet som er stilt som at man henger seg for mye opp i eksempelimplementasjonen i beskrivelsene av  design patterns, og at man kanskje går glipp av det som jeg oppfatter som det viktigste; problemet som skal løses, og den generelle og mer eller mindre universelle strategien for å løse det.

Eksemplene er viktige for dem som bruker et "begrenset" språk; mange av mønstrene fra Gang of Four fokuserer på C++, og hvordan man best lager fleksibel kode der – mens de vil se ganske anderledes ut i for eksempel Ruby. Det er til eksempel ingen vits å basere Strategy Pattern på et interface når man har duck typing.

Jeg føler jeg allerede har lært mye av å holde patterns-foredraget mitt, skrive denne bloggserien, og svare på dette spørsmålet. Om du ser noen hull eller selvmotsigelser i det jeg sier nå er jeg veldig interessert i å høre hva du har å si, for det betyr bare at jeg får en mulighet til å lære enda mer!

Ward Cunningham er en smart fyr, og jeg vil avslutte med å sitere noe han har skrevet på The Portland Pattern Repository:

"Patterns link together in the mind so that one pattern leads to another and another until familiar problems are solved. That is, patterns form languages, not unlike natural languages, within which the human mind can assemble correct and infinitely varied statements from a small number of elements."

PS: Vil du lese et par interessante artikler om patterns kan jeg anbefale Steve Yegge's Singleton Considered Stupid fra 2004 (fra hans tid som utvikler i Amazon) og Code's Worst Enemy fra 2007 (etter at han begynte å kode for Google). Steve provoserer alltid, men har uansett mye fornuftig å si i refleksjonene sine.


comments powered by Disqus