Wednesday, July 18, 2007

Functional idioms, Take Three

In a hypothetical project in which the Law of Demeter is completely ignored navigation through objects is allowed: we can do A.B.C.D.E.DoSomething(). This has a lot of negative effects, already spoken/written, I'm not going into details.
  • My 1st suggestion would be to play by the rules, and pull the DoSomething(...) through the hierarchy up to A, where you need it.
  • But what if you cannot do it ("it is not the way we do it in this project") ? What if, to make the matters worse, every element in the chain could be null (and not a NullObject) ? The chain would explode in a cascade of if-then-else-s to check every element for null, etc...
    • Comega has something like int? = A.B.C.GetSomeIntValue(...)
    • We (C#) could do:

created.PackungsgroessenEinheitText = Chain.On.Nullables<IArtikel, INormalArtikel, Packungsgroesse, string>(

artikel,

delegate(IArtikel x) { return x as INormalArtikel; },

delegate(INormalArtikel x) { return x.Packungsgroesse; },

delegate(Packungsgroesse x) { return string.Format("{0} {1}", x.Menge, x.Einheit); }

);

    • we navigate throught the chain with delegates. The navigation is interrupted on the 1st null hit.
    • If we watch the "chain" implementation:

public class Chain {

private Chain() {}

public static Chain On { get { return new Chain(); } }

public R Nullables(S input, Func fun_1)

where S : class

where R : class {

if (input == null) {

return null;

}

return fun_1(input);

}

public R Nullables(S input, Func fun_1, Func fun_2)

where S : class

where R1 : class

where R : class {

return Nullables(Nullables(input, fun_1), fun_2);

}

public R Nullables(S input, Func fun_1, Func fun_2, Func fun_3)

where S : class

where R1 : class

where R2 : class

where R : class {

return Nullables(Nullables(Nullables(input, fun_1), fun_2), fun_3);

}

}




No comments: