Podział logiki programu na pliki

0

Witam, piszę prostą aplikację desktopową. Baza danych + klient operujący na tej bazie.
Bazę mapuję sobie w kliencie przy pomocy EF.
Chciałbym oddzielić warstwę prezentacji, pośredniczącą oraz tą mapującą Bazę na oddzielne biblioteki dll.
Problem pojawia się w momencie próby połączenia tego w całość.
Warstwa pośrednicząca oraz mapująca bazę muszą komunikować się w obie strony.
Nie mogę dodać ich wzajemnie w swoje referencje ponieważ nastąpi błąd.
Ktoś może mnie naprowadzić jak ugryźć ten problem?

2

Warstwa wyższa powinna korzystać z warstwy niższej, komunikacja w drugą stronę jest niedozwolona i niepotrzebna.
Czyli prezentacja korzysta z logiki biznesowej, a ta z warstwy dostępu do danych.

0

Ok wiem, wzorce projektowe itp.
Myślałem że istnieje jakaś sztuczka pozwalająca to obejść, lecz nie mieszająca zbyt w kodzie.
W każdym razie piszę teraz zgodnie z konwencją (warstwa wyższa odwołuje się tylko do tej bezpośrednio pod nią).
Pytanko: czy warstwa wyższa wywołując metodę z niższej, może do niej przekazywać swoje obiekty?
Czy powinna opierać się wyłącznie na tym co metoda z warstwy niższej zwraca?

0

W jakim sensie swoje obiekty? Obiekty na których operuje warstwa niższa muszą być jej znane, czyli muszą to być obiekty z tej warstwy.

0

Może konkretny przykład:
Warstwa środkowa wyciąga sobie, poprzez warstwę najniższą, jakieś dane z bazy.
Warstwa prezentacji, wywołując metodę z warstwy środkowej, przekazuje jej w argumencie tej metody obiekt DataGridView, a warstwa środkowa binduje dane do tego obiektu.
Oczywiście w tej sytuacji i warstwa prezentacji i środkowa posiadają referencje do System.Windows.Forms.
Czy takie rozwiązanie jest dopuszczalne?
Gdybym miał przekazywać te dane przez wynik metody, musiałbym stworzyć specjalne struktury do przerzucania tych danych między warstwami - sporo dodatkowego kodu :/

0
kreis84 napisał(a):

Warstwa prezentacji, wywołując metodę z warstwy środkowej, przekazuje jej w argumencie tej metody obiekt DataGridView, a warstwa środkowa binduje dane do tego obiektu.
Oczywiście w tej sytuacji i warstwa prezentacji i środkowa posiadają referencje do System.Windows.Forms.
Czy takie rozwiązanie jest dopuszczalne?

Skoro wszystko operuje na kontrolkach GUI, to masz tylko jedną warstwę. Warstwy polegają na tym, że są oddzielne, nie znają swoich wewnętrznych implementacji, a warstwa niższa nic nie ustawia w warstwie wyższej - to warstwa wyższa pobiera dane z niższej i je ustawia u siebie.

Już lepiej by było, gdybyś do przekazywania danych między warstwami użył klasy DataTable i DataRow. Zresztą, wszystko jest lepsze do tego celu niż kontrolki GUI, które służą przecież do wyświetlania danych, a nie ich przesyłania.

Gdybym miał przekazywać te dane przez wynik metody, musiałbym stworzyć specjalne struktury do przerzucania tych danych między warstwami - sporo dodatkowego kodu :/

Za to masz pełną kontrolę nad kodem i tym, co się dzieje w aplikacji, do własnych klas możesz dodać własną logikę (np. właściwości wyliczane na podstawie danych z bazy), czego z oczywistych względów do DataGridView nie dodasz.
Całość będzie też łatwiejsza do rozbudowy, np. jeśli okaże się, że trzeba zrobić eksport do pliku XML, to dla normalnej klasy są to trzy linijki kodu, a dla DataGridView będziesz pisał pętle przez kilka godzin, wyjdzie z tego sporo zbędnego kodu, który na dodatek będzie niewydajny.
Ciekaw jestem też jak rozwiązujesz problem stronicowania/wirtualizacji dla DataGridView, które przekazujesz w całości do jakiejś niższej warstwy. Obstawiam, że w ogóle i wczytujesz całą tabelę na raz, co jest bardzo złym pomysłem.

0

I dobrze obstawiasz. Co prawda każda kontrolka będzie miał co najwyżej kilkadziesiąt pozycji, ale rozumiem o co ci chodzi.
Zafiksowałem się na tym że warstwa prezentacji nie powinna robić takich rzeczy jak bindowanie danych - w końcu powinna tylko prezentować dane.
Dla tego robiłem to w warstwie środkowej.
Mój błąd.
Czyli znów przerabiam kod, swoją drogą to też dobre ćwiczenie :)

Warstwy polegają na tym, że są oddzielne, nie znają swoich wewnętrznych implementacji, a warstwa niższa nic nie ustawia w warstwie wyższej - to warstwa wyższa pobiera dane z niższej i je ustawia u siebie.

Definiuję w warstwie logiki typy, którymi opakuję dane, a potem te obiekty przekazuję do warstwy wyższej.
To jest prawidłowe podejście?

Są jeszcze jakieś inne sensowne sposoby?
Wiem że nie mogę użyć typów nie jawnych (var) - to byłoby dopiero elastyczne rozwiązanie :)

1
kreis84 napisał(a):

Zafiksowałem się na tym że warstwa prezentacji nie powinna robić takich rzeczy jak bindowanie danych - w końcu powinna tylko prezentować dane.

Ale bindowanie to jest właśnie część logiki prezentacji. Bo to warstwa prezentacji zna swoje kontrolki i wie, jak się do nich zbindować (np. czy automatycznie, czy trzeba użyć pętli).

Czyli znów przerabiam kod, swoją drogą to też dobre ćwiczenie :)

Poczytaj o Model View Presenter, w nim jest to ładnie rozdzielone. W skrócie:

  1. definiujesz interefejsy Widoków, na których operuje logika prezentacji czyli Presentery;
  2. warstwa GUI implementuje te Widoki, i w nich binduje dane odpowiednio do swojej technologii;
  3. Model to cała reszta, czyli źródło danych i logika biznesowa.

Definiuję w warstwie logiki typy, którymi opakuję dane, a potem te obiekty przekazuję do warstwy wyższej.
To jest prawidłowe podejście?

Wiem że nie mogę użyć typów nie jawnych (var) - to byłoby dopiero elastyczne rozwiązanie :)

var to nie jest typ niejawny tylko słowo kluczowe pozwalające na nie pisanie pełnej nazwy typu przy deklarowaniu zmiennej. Typ i tak jest statycznie wnioskowany na etapie kompilacji.

0

Ok, dzięki somekind, rozjaśniłeś mi trochę niektóre zagadnienia.

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