Min favorit pattern-kombo

Skrevet - Thursday, August 14th, 2008 kl. 21:43 | Kategori - * Kodning

Agile processer snakker tit om anvendelsen af patterns. Jeg er ved at have nogenlunde styr på de mest almindelige GoF patterns (hvem hulen bruger Monostate…), og i dag fandt jeg en meget lækker og elegant kombination, som måske vil ændre min måde at skrive kode for alvor.

De fleste har nok hørt om IoC – Inversion of Control. Egentlig handler det meget om at bryde afhængigheder, ved at bruge DI (Dependency Injection). Dvs. at istedet for at to klasser er direkte afhængige af hinandens implementation – er de alene afhængige af hinandens interface. IoC udmærker sig ved at gøre det muligt først at lave koblingen run-time – og for de noget mere avancerede scenarier give mulighed for at udskifte konkrete implementationer run-time.

Vi bruger IoC via Windsor Castle – et fantastisk Framework, som virkelig gør det nemt at opsætte afhængigheder (kræver at man kan stave rigtigt i sin XML… men ellers rimelig nem at sætte op). I princippet kan vi på den samme installation køre med forskellige opsætninger for to forskellige brugere… måske et lidt tænkt scenarie, men alligevel meget kraftfuldt.

Den anden halvdel af min kombo er MVP – Model View Presenter. Her går det ud på at separere design fra logik via DI. Ideen er at man indsætter en Mediator (presenter) imellem view og model (typisk en domain service eller direkte på et domæneobjekt). Dvs. at presenteren får kald fra viewet, når brugeren interagerer og formidler det videre til modellen, som så kan lave call-backs osv. View og model kender ikke hinanden – kun presenteren kender begge. MVP kan godt virke lidt uelegant, fordi viewet initierer presenteren med sig selv som argument i constructoren i de fleste implementationer.

Det er muligt at trække afhængighederne fra MVP ud i en noget IoC lignende med en PresenterService.CreateViewPresenter()-noget, men så er vi blot afhængige af en ny klasse.

Nu kommer komboen så. Via IoC udleder vi den konkrete implementation af presenteren direkte og udleder de konkrete implementation af model og view – altsammen run-time.

Okay – det var mange termer på en gang – først den ‘gammeldags’ (lettere modificeret til noget a’la ServiceLocator) implementation af MVP:


ISomeView _view = new SomeView();
_view.Show();

public class SomeView : Window, ISomeView
{

private ISomePresenter presenter
public SomeView()
{

InitializeComponent();
presenter = PresenterService.GetSomePresenter(this);

}
protected override OnInit()
{

presenter.Init();

}


}

public class SomePresenter : ISomePresenter
{

private ISomeView _view;
private ISomeService _service;

public SomePresenter(ISomeView view)
{

_view = view;
_service = ServiceService.GetSomeService();

}
public void Init()
{

do some wiring here…

}

}

public class SomeService : ISomeService
{

public SomeService(){}

}

Ingen direkte koblinger – dejligt – men der er mange ekstra klasser i spil. Det er nemt at teste hver af dem med mocking, men det virker uelegant.

Nu til vores nye løsning:


WindsorContainer _container = new WindsorContainer();
ISomePresenter _presenter = _container.Resolve<ISomePresenter>();
_presenter.View.Show();

public class SomeView : Window, ISomeView
{

public SomeView()
{

InitializeComponent();

}

}

public class SomePresenter : ISomePresenter
{

public SomePresenter(ISomeView view, ISomeService service)
{

Do some wiring

}

}

public class SomeService : ISomeService
{

public SomeService(){}

}

Hvis det ikke er mere elegant – så må du kalde mig Herrr YAGNI for al evighed. Ooh – og eftersom vi bruger WPF… så kan designet ligge i ‘løse’ XAML-filer, som vi compiler run-time… og vi kan dermed skifte dem imens applikationen kører. Okay – træerne gror ikke ind i himlen. Der er en pris at betale for den _meget_ løse kobling… performance may suffer. Men det vil tiden vise, når vi får de første implementationer op at køre.

Feed | Trackback |

Post a Comment