Arbejder man med MVP pattern i sine webapplikationer, har man en øget mulighed for at gøre sine WebForms testbare. Man kan teste sin kode i et isoleret miljø, og mocke sine afhængigheder, så man på den måde kan kontrollerer input til sit forventede output. Jeg har hidtil afkoblet de forskellige afhængigheder ved at bruge Constructor Injection, og det har fungeret fint, i både ny og eksisterende kode. I ny kode, er det jo let at lave en konstruktør, der tager alle afhængige objekter som parametre, og gøre den parametreløse konstruktør privat, og i eksisterende kode, at implementerer afhængighedskonstruktøren, og så kalde den fra den parametreløse konstruktør via "Poor mans Dependency Injection":
[code=csharp]public class MyObject
{
private IModel m_model;
public MyObject()
: this(new ConcreteModel())
{
}
public MyObject(IModel model)
{
m_model = model;
}
}[/code]
Den løsning, har den fordel, at man får gjort klassens afhængigheder klart i konstruktøren, og kommunikerer en slags kontrakt til klienten. Problemet med denne løsning, er bare at man overtræder indkapslings princippet i OOP. Det er pludselig klientens problem at instantierer en IModel før den kalder konstruktøren. Det er selvfølgelig en lille ting, og man kan jo gøre den afhængige konstruktør internal, så den kun kan ses af test-klasserne. Fint nok, men det stinker stadig...
Hvad så med at se lidt på hvordan MS, har løst problemet, i System.Web? Her bruges i vid udstrækning en Service Locator med en Singleton. Se f.eks. på Membership-klassen. Den bruges til at lokaliserer en MembershipProvider, som angivet i web.Config, og gør det muligt for os at bruge de forskellige funktionaliteter igennem et ensartet og fuldstændigt indkapslet. På den måde, er det jo også muligt at indsætte mock'ede objekter i sine unittests på projektniveau. Man kan altså skrive sine tests, uden at skulle instantierer afhængighederne inden kald til konstruktøren - det vil bringe test-kode endnu tættere på produktions-kode. Ud over test aspektet, så får man jo også en afkobling af afhængigheder, der gør at applikationen kan være noget letere at vedligeholde, og skalerer i fremtiden.
Det bringer mig frem til pointen i denne post: Har man behov for et framework, som StructureMap eller Windsor Container?
Ja det kommer vel an på hvor mange steder man bruger den form for afkobling. Er der kun tale om at man bruger et par DataProvidere, kan det virke lidt som overkill, men har man først fået mønstret lidt ind under hude, så kan man altså spare en del "blikenslager-kode" som jeg ser det.
IoC frameworks er et af de helt store buzz-words i dag, men har du erfaring med IoC frameworks på mindre web-applikationer? Hvis ja, så smid en kommentar, for jeg leder stadig med lys og lygte til det rigtige mix i de systemer jeg har fingrene i.