BDD: Metoden der kan håndtere alt vs. strategy pattern

Skrevet - Saturday, September 6th, 2008 kl. 17:26 | Kategori - Kodning

Version 0.12 af EconomyDeluxe er online her. Der er sket en del refaktorering (efterhånden en fast bestanddel) - alle behaviour projekterne er nu samlet i et projekt og EconomyDeluxe er splittet op i to - en .exe/.xbap og en .dll, som indeholder alt logikken. Der er to grunde til opsplitningen - Castle Windsor kan ikke udlede classer fra en .exe og jeg vil nu kunne tilføje en web-style wpf applikation med samme logik.

Primært er der nu tilføjet den første MVP - jeg har i den forbindelse lavet en hjælpeklasse (Property2WPFControlMapper) som skal sørge for at bygge propertygrids. Det er ikke første gang jeg bygger sådan en klasse, så det gik forholdsvis hurtigt med at bygge den. Jeg kan bygge et fuldstændig databundet view med textboxe, comboboxe osv. med en linje kode og en hel bunke reflection. I vores projekt på arbejde har jeg lavet samme klasse, bare noget mere sofistikeret og mere funktionalitet. Her rendte vi ind i, at alle andre end mig havde svært ved at gennemskue den. Problemet består i at der er forholdsvis mange scenarier for en given property - og den control, der kommer ud af det, har meget forskellig adfærd - det resulterede i en del if-then-else-if og switch-case.

Vores projektleder bad mig anvende strategy-specification pattern i en refactorering. Jeg må indrømme, at min kode er blevet noget mere læsbar. Der er dybest set 4 forskellige scenarier (strategies), som giver mening i vores domæneobjekter:

Jeg har oprettet en IControlStrategySelector, som fungerer som min specification, dvs. den der skal sørge for logikken i hvilken strategi, der bliver valgt. Derefter har jeg lavet 4 IControlStrategy-classer, som alle implementerer 2 simple metoder - CreateControl() og IsSatisfiedBy(). Den første laver controllen ud fra en PropertyInfo, mens den anden bestemmer hvorvidt strategien kan håndtere den givne PropertyInfo.

Eftersom jeg kun skal bruge en strategi per PropertyInfo, har jeg lavet selector’en temmelig simpel - jeg har lavet en IList, som jeg itererer henover, indtil jeg finder en strategi, der opfylder mine behov. Derfor er rækkefølgen vigtig - default-strategien er textboksen, så den ligger til sidst i IList’en. Strategien for komplekse ValueTypes er lavet generisk fordi jeg skal have en datasource med, som ikke er ens for de forskellige typer. På nuværende udviklingsstadie har jeg kun en type, der skal ligge i en combobox - ILedgerAccount, men der vil komme flere.

Resultat: Min oprindelige hjælpeklasse var på ca. 150 linjer med mange nestede if-then-else strukturer. Nu er den splittet op i 2 interfaces (10 linjer tilsammen), 4 implementationer (ca 20 linjer/stk) + 1 abstract klasse(25 linjer) for IControlStrategy samt 1 implementation (23 linjer) af IControlStrategySelector - og den oprindelige klasse er nede på 43 linjer. Netto er der altså tilføjet ca. 30 linjer kode og 8 filer. Til gengæld… overskueligheden er steget med mange grader og kompleksiteten for andre end mig er faldet markant.

EDIT: Jeg er klar over, at man normalt ville lade Specifications og Strategies være to forskellige klasser for bedre at overholde SoC og SRP (se evt. her). I den her sammenhæng virker det dog som needless complexity eftersom det ikke vil udvide sig voldsomt med tiden (det er trods alt en gennemprøvet rutine, der er refactoreret til pattern). Lad os kalde det Compact Specification/Strategy pattern…

Feed | Trackback |

Post a Comment