Jeg har tidligere haft interesse i at decouple systemer og assemblies, dels for at opnå en mere modulær opbygning, og nu samtidigt er det jo snart blevet total hype pga. TDD, unittesting og mocks. Jeg har tidligere studeret lidt [EBP], det er virkelig genialt - ingen tvivl om det, men også lidt omstændigt lige at udvikle til brug for en webapplication eller mindre Winapplication.
Så det var på tide jeg satte mig lidt ind i DI (Dependency Injection). DI består kort fortalt i at undgå at instanciere classer i sine classer, i det øjeblik man gør det vil man skabe dependencies som ikke nemt lader sig udskifte. Derudover gør det også testing/ mocking til et sandt helvede. Jeg har kigget lidt rundt på forskellige DI-framework; Spring.NET, Autofac, Ninject, Castle Windsor og StructureMap.
Måden man undgår at skabe en unødig binding imellem sine klasser og assemblies er som sagt vha. Dependency Injection, DI handler om at man skaber eller wirer forbindelser imellem klasser et eksternt sted fra evt. igennem XML-configuration eller Fluent-programming, det forklarer jeg om senere.
Med unødig binding/ high coupling som man ofte ser i kode: (pyt med at eksemplet er lidt trivielt og besynderligt med den average, i gamle dage krævede det et loop, dividende og check for at der var personer i collectionen – tider jeg husker, men ikke ligefrem savner [:D] )
WrongBinding har en stærk binding til Personklassen igennem instancieringen i linje 7.
public class WrongBinding
{
IList persons;
public WrongBinding()
{
persons = new Person().GetSomePersons();
}
public void CalculateAverageHeight()
{
decimal averageHeight;
if (persons.Count > 0)
averageHeight = persons.Average(x => x.Height);
}
}
public class Person
{
public int Height { get; private set; }
public string Name { get; private set; }
public List GetSomePersons()
{
return new List()
{
new Person{Height = 185, Name = "Jan Gintberg"},
new Person{Height = 178, Name = "Nicolaj Kopernikus"},
new Person{Height = 180, Name = "Thomas Bo Larsen"}
};
}
}
Jeg vil næsten vove den påstand at ser man sådan noget kode bør der overvejes en refactoring, medmindre projektet er så lille og begrænset at det nærmest blot er en mock-up/ prototype/ demo i sig selv for at belyse og analysere problemområder under projektet. Nu skal jeg ikke gøre mig mere hellig end hvad godt er, tag et kig på den kode jeg skrev for ½år siden, jojo.. jeg kan skam også kode med stærk kobling *LOL*. Jeg vil dog vove den påstand at jeg er kommet lidt videre henimod noget der ligner noget loose-coupling ;)
Som et lille tip har jeg udviklet en extension til IEnumerable, på den måde undgår man helt de trivielle check:
public static class JKExtensions
{
public static decimal? AverageOrNull(this IEnumerable type, Func selector)
{
try
{
return type.Average(selector);
}
catch (InvalidOperationException)
{
return null;
}
}
}
På den måde kan man blot kalde Average sådan her:
var averageHeight = persons.AverageOrNull(x => x.Height);
Vupti.. ingen redundant if-then opslidende tastearbejde – Remember DRY ?
Well, tilbage til emnet….
Det første jeg bemærkede ved Spring.NET var at alt konfiguration skulle skrives i XML, nu er jeg sådan med tiden blevet mere og mere modstander af XML. Til at starte med var det jo supersmart og totalt hipt, meeeenn…. ligefrem XML-programmering er lige at strække formattet lidt for langt IMHO(another post).
Så Spring.NET droppede jeg rimeligt hurtigt igen. Det skal dog lige nævnes at Spring.NET er meget andet end blot DI, hvilket jo naturligvis også skal tages med i overvejelserne, men nu var jeg kun på udkig efter et lightweight og decideret DI-framework.
Så kiggede jeg på Castle Windsor, her stødte jeg på et begreb kaldet Fluent Interface , Castle Windsor så rigtigt interessant ud og havde det ikke været for min lidt rebelske attitude så…. Nu var min nysgerrighed vakt og jeg har altid haft det sådan, at selvom det ligger i toppen af Googlesøgningen behøver det jo ikke være det eneste og bedste.
Jeg fandt 2 websider som har gennemgået de forskellige frameworks rimeligt grundigt, http://blog.ashmind.com/index.php/2008/08/19/comparing-net-di-ioc-frameworks-part-1/ og http://www.codinginstinct.com/2008/04/ioc-container-benchmark-unity-windsor.html
Efter at have gennemlæst begge posts grundigt gik jeg videre med Autofac, lille og lækkert DI-framework. Jeg bankede en hurtig test sammen, men jeg fik en fornemmelse af at det ikke var helt gennemarbejdet, jeg kan dog sagtens tage fejl – så undersøg det selv :)
Så videre til Ninject og her må jeg nok sige, der for alvor fik åbnet mine øjne for DI. Ninject har en rigtigt interessant Dojo som beskriver DI på en nem og forståelig måde, her er god mulighed til at blive bekendt med hvad man bør forlange/ forvente af et DI-framework. Jeg fik dog aldrig kodet noget med Ninject, jeg ved ikke – syntes vidst der var lidt forvirring om performance hos http://www.codinginstinct.com/2008/04/ioc-container-benchmark-unity-windsor.html .. men pludselig sad jeg med StructureMap.
Jeg fortsætter med part 2 i den kommende tid, så stay tuned :)