Odpowiedni konstruktor vs metoda inicjalizacyjna w interfejsie

0

Cześć, tworzę sobie system, który działa na zasadzie engine <-> klient (interfejs użytkownika).
Generalnie chodzi o to, żeby klientów mogło być wielu na różne platformy, więc większość logiki powinna być obsługiwana przez engine. No takie to trochę MVC, ale nie w 100% klasyczne.

I teraz naszła mnie taka myśl. Mam sobie interfejs do widoku: IMyView.
W pewnym momencie framework musi utworzyć taki widok (wykorzystuje do tego IoC):

IMyView view = objFactory.Resolve<IMyView>();

Okazuje się jednak, że jeden z widoków powinien mieć kilka prostych parametrów w konstruktorze, coś w ten deseń:

public MyView(bool bValue, int iValue)
{
}

W zależności od tych parametrów, na widoku jedna kontrolka powinna być aktywna bądź nie. Więc teraz można to wykonać na dwa sposoby. Albo wymuszając niejawnie postać konstruktora i zrobić coś w stylu:

IMyView view = objFactory.ResolveWithParameters(true, 1);

albo przenosząc część inicjalizacji do metody przedstawionej w interfejsie. I wtedy wyglądałoby to tak:

public interface IMyView: IView
{
    void LateConstructor(bool bValue, int iValue);
}

a wywołanie:

IMyView view = objFactory.Resolve<IMyView>();
view.LateConstructor(true, 1);

Bardziej naturalne wydaje mi się podejście z dodatkową metodą w interfejsie. Minusem jest to, że framework przy każdorazowym tworzeniu takiego widoku musi pamiętać o tym, żeby wywołać tą metodę (można zrobić to mądrze oczywiście z użyciem jakiegoś managera widoków i wtedy ten problem niejako odpada, jednak trzeba tworzyć i używać managera/fabrykę widoków, który nie do końca wydaje się potrzebny, skoro mamy objFactory).

Z drugiej strony wymuszenie odpowiedniego konstruktora w klasie widoku wydaje się być wygodniejsze, ale mam tu wątpliwości od strony architektonicznej. Co o tym sądzicie?

Co do pytań w stylu: "A nie możesz tego zrobić za pomocą objFactory, który już masz?". Odpowiadam: nie. Bo objFactory to abstrakcja od strony engine. Tak naprawdę klient implementuje objectFactory, dzięki czemu np. w Winforms mogę wykorzystać AutoFAC, a na Androidzie coś zupełnie innego.

1

Jeśli to są wartości inicjalizacyjne dla obiektu, które ogólnie nie mogą się zmieniać z zewnątrz, to lepiej byłoby użyć konstruktora. Jeśli aktywnością kontrolki da się i tak sterować z zewnątrz, to można użyc metody.

0

Nie mogą się zmieniać. Jednak to byłoby trochę uciążliwe robić to w konstruktorze, bo tak naprawdę różne widoki mogą potrzebować różnych zależności. Np. widok od WinForms może potrzebować zależności do kontrolera A, a widok z Androida może potrzebować zależności do dwóch innych kontrolerów. I tu się boję, że mogą być problemy z odpowiednim Resolvem przez kontener IoC.

2

No ale żeby obsłużyć złożone przypadki IoC zwykle umożliwia używanie metod tworzących czy fabryk, nie wystarczą one?

Jeśli nie wystarczą to bym się zastanowił czy warto dalej używać IoC, bo jeśli IoC rzuca Ci kłody pod nogi to wiedz że się coś dzieje, skoro narzędzie które ma ułatwiać pracę sprawia że musisz robić coś by obejść jego niedoskonałości. Oczywiście jestem bardzo stronniczy w tej kwestii, bo jestem zadeklarowanym zwolennikiem używania ręcznego wstrzykiwania zależności (pure dependency injection) w większości przypadków i stosowania IoC w ostateczności.

Co do używania odrębnej metody inicjalizującej, to bym tez spojrzał na kto ją ma wywołać, czy moduł wysokopoziomowy aka użytkownik, czy moduł niskopoziomowy aka infrastruktura lub framework.
Jeśli za jej wywołanie odpowiada modułu niskopoziomowy, to jak najbardziej byłbym w stanie z tym żyć.
Jeśli za jej wywołanie odpowiada moduł wysokopoziomowy, czyli użytkownik musi zawsze pamiętać by ją wywołać po stworzeniu obiektu i może się stać coś złego jak tego zapomni, no to mamy klops.

0

Właśnie tu będzie to robił moduł niskopoziomowy. Chyba w takim razie zostanę przy tym, oszczędzi to ewentualnych problemów z tworzeniem obiektu przez kontenery.

1 użytkowników online, w tym zalogowanych: 0, gości: 1