Nie zdawałem sobie sprawy jak bardzo łatwiej pisać kod w oparciu o interfejsy. Zamiast tworzyć od razu klasy i martwić się ich implementacją, możemy odłożyć to zadanie na przyszłość. Dzięki temu można stworzyć hierarchię zależności między typami, nie martwiąc się zbytnio wnętrzem interfejsu.
Spójrzmy na mój interfejs IData
:
public interface IData
{
IMetadata Metadata { get; }
INode RootNode { get; }
IFileAccess FileAccess { get; }
}
Rozdzielając jego funkcjonalność na trzy interfejsy, utrzymuję większy porządek w kodzie oraz mogę odłożyć planowanie danej funkcjonalności na później. Zacząłem od definicji interfejsu INode, ponieważ jest to rdzeń moich typów danych:
public interface INode
{
INode GetParent();
IEnumerable<INode> GetChildren();
IEnumerable<IAttribute> GetAttributes();
IValue Value { get; set; }
}
Znowu, nie muszę myśleć jak będzie wyglądało IValue
, czy IAttribute
do momentu gdy będę implementował ten interfejs. Pozwala mi to bezpiecznie commitować, ponieważ mój kod będzie się kompilował i jeśli ktoś sklonuje sobie moje repo, nie dostanie masy błędów. Oczywiście mógłbym iść w ścieżkę `throw new NotImplementedException()` co robi VS przy automatycznym tworzeniu nowych metod, ale nie jest to zbyt eleganckie.