Mam poważne wątpliwości co do projektu mojej aplikacji internetowej.
Chciałem oddzielić logikę biznesową od interfejsu, dlatego stworzyłem interfejs API sieci Web, który obsługuje wszystkie żądania do bazy danych.
Jest to interfejs API sieci Web ASP.NET z platformą Entity oraz jednostką pracy i ogólnym wzorcem repozytorium. Jak dotąd wszystko jest dobrze.
PROBLEM
Potrzebuję pomocy, ale nie mogę znaleźć skutecznego sposobu udostępniania obiektów między interfejsem API a aplikacją.
Nie chcę serializować bezpośrednio obiektu encji, pomyślałem, że byłoby to złą praktyką, ponieważ jeśli zmieni się model encji, mogę skończyć serializacją dużych obiektów bez powodu.
Jak to teraz zaimplementowane
Ponieważ moim interfejsem jest aplikacja sieci Web ASP.NET w języku C #, a mój interfejs API jest w języku C #, stworzyłem wspólną bibliotekę z definicją wszystkich moich klas, które chcę udostępniać między nimi.
Wiem, że to rozwiązanie nie zadziała, kiedy opracuję aplikację na Androida. Będę musiał ponownie utworzyć klasy w Javie, ale to nie jest mój największy problem.
Problem polega na tym, że mam wrażenie, że zawsze przekształcam swoje obiekty.
PRZYKŁAD
Oto przykład mojego przepływu pracy:
Zaczynam od modelu zawierającego wszystkie obiekty i adnotacje danych dla mojego formularza, a następnie użytkownik wysłałby ten model do kontrolera.
W kontrolerze muszę przekonwertować ten model na klasę we wspólnej bibliotece, a następnie wysłać ten obiekt do mojego interfejsu API.
Następnie kontroler w moim interfejsie API przechwytuje wywołanie i przekształca ten obiekt w obiekt encji, aby zaktualizować bazę danych.
Mam więc 3 klasy
- Model widoku ze wszystkimi adnotacjami danych do sprawdzania poprawności (klient)
- Wspólne klasy bibliotek do udostępniania obiektów (DLL)
- Klasy encji (API)
Mam wrażenie, że robię coś naprawdę nie tak. Czy jest coś bardziej eleganckiego? Chciałbym upewnić się, że mam dobre rozwiązanie tego problemu, zanim projekt stanie się zbyt duży.
Odpowiedzi:
Wiem, że może się wydawać, że cały czas konwertujesz obiekty do przodu i do tyłu między obiektami bazy danych, obiektami przesyłania danych, obiektami klienta z logiką sprawdzania poprawności i tak dalej, ale powiedziałbym, że nie, nie robisz nic złego .
Każdy z tych obiektów może reprezentować tę samą jednostkę informacji, ale mają bardzo różne obowiązki. Obiekt bazy danych jest interfejsem komunikacyjnym z bazą danych i powinien być przechowywany w warstwie bazy danych, ponieważ może zawierać różne adnotacje metadanych bazy danych i / lub niepotrzebne szczegóły dotyczące implementacji bazy danych.
Obiekt do przesyłania danych stanowi interfejs komunikacyjny z użytkownikami interfejsu API. Powinny być tak czyste, jak to możliwe, aby ułatwić korzystanie z różnych języków / platform. Może to nakładać pewne ograniczenia na ich wygląd i zachowanie w zależności od tego, jakich klientów interfejsu API chcesz obsługiwać.
Obiekty klienta z logiką sprawdzania poprawności tak naprawdę nie są częścią twojego projektu API, są częścią twojego projektu konsumenckiego. W tym przypadku nie mogą być one identyczne z obiektami przesyłania danych, ponieważ dodajesz na nich dodatkową logikę specyficzną dla klienta (w tym przypadku atrybuty sprawdzania poprawności), o której serwer nic nie wie (i nie powinien nic wiedzieć!) policz te obiekty jako część interfejsu API, ponieważ tak naprawdę nie są. Są one bardzo specyficzne dla aplikacji konsumenckich, a niektóre aplikacje wykorzystujące interfejs API mogą nawet nie musieć tworzyć tych obiektów i równie dobrze mogą przetrwać tylko na obiektach do przesyłania danych. Na przykład, jeśli nie potrzebujesz żadnej weryfikacji, nie potrzebujesz dodatkowej warstwy obiektów, które są całkowicie identyczne z obiektami do przesyłania danych.
Wydaje mi się, że każdy z trzech typów obiektów bardzo ładnie mapuje się na jedną odpowiedzialność, jaką jest czyste kodowanie i dobra praktyka. Niestety, czysty kod i dobre praktyki czasami oznaczają, że piszesz dużo dodatkowego kodu i przeskakujesz dodatkowe kółka „tylko dlatego”. Podczas kodowania może być trudno docenić wartość, jaką to daje - ale jak tylko wydasz aplikację i zaczniesz ją obsługiwać lub dodawać nowe funkcje do następnej wersji, prawdopodobnie zaczniesz doceniać, że poświęciłeś czas na w pierwszej kolejności należy odpowiednio rozdzielić te obawy. (Nie wspominając o tym, że ty
Nienawidzę także pisania kodu konwersji między różnymi typami obiektów, jak ten, ale moje rozwiązanie jest zwykle jedno z następujących:
źródło