Część 2. Architektura
Kluczowym zestawem tworzenia aplikacji międzyplatformowych jest utworzenie architektury, która pozwala zmaksymalizować udostępnianie kodu na różnych platformach. Przestrzeganie następujących zasad programowania obiektowego pomaga w tworzeniu dobrze zaprojektowanej aplikacji:
- Hermetyzacja — zapewnienie, że klasy, a nawet warstwy architektury uwidaczniają tylko minimalny interfejs API, który wykonuje wymagane funkcje, i ukrywa szczegóły implementacji. Na poziomie klasy oznacza to, że obiekty zachowują się jako "czarne pola" i że korzystanie z kodu nie musi wiedzieć, jak wykonują swoje zadania. Na poziomie architektury oznacza to implementowanie wzorców, takich jak fasada, które zachęcają uproszczony interfejs API, który organizuje bardziej złożone interakcje w imieniu kodu w bardziej abstrakcyjnych warstwach. Oznacza to, że kod interfejsu użytkownika (na przykład) powinien być odpowiedzialny tylko za wyświetlanie ekranów i akceptowanie danych wejściowych użytkownika; i nigdy bezpośrednio nie wchodzi w interakcję z bazą danych. Podobnie kod dostępu do danych powinien odczytywać i zapisywać tylko w bazie danych, ale nigdy nie wchodzi w interakcje bezpośrednio z przyciskami lub etykietami.
- Rozdzielenie obowiązków — upewnij się, że każdy składnik (zarówno na poziomie architektury, jak i klasy) ma jasny i dobrze zdefiniowany cel. Każdy składnik powinien wykonywać tylko zdefiniowane zadania i uwidaczniać tę funkcjonalność za pośrednictwem interfejsu API dostępnego dla innych klas, które muszą go używać.
- Polimorfizm — programowanie w interfejsie (lub klasie abstrakcyjnej), która obsługuje wiele implementacji, oznacza, że podstawowy kod może być napisany i współużytkowany na różnych platformach, a jednocześnie wchodzić w interakcje z funkcjami specyficznymi dla platformy.
Naturalny wynik jest aplikacją modelowaną po świecie rzeczywistym lub abstrakcyjnych jednostkach z oddzielnymi warstwami logicznymi. Rozdzielenie kodu na warstwy ułatwia zrozumienie, testowanie i konserwację aplikacji. Zaleca się, aby kod w każdej warstwie był fizycznie oddzielony (w katalogach lub nawet oddzielnych projektach dla bardzo dużych aplikacji), a także logicznie oddzielony (przy użyciu przestrzeni nazw).
Typowe warstwy aplikacji
W tym dokumencie i analizach przypadków odwołujemy się do następujących sześciu warstw aplikacji:
- Warstwa danych — trwałość danych nietrwałych, która może być bazą danych SQLite, ale może zostać zaimplementowana przy użyciu plików XML lub dowolnego innego odpowiedniego mechanizmu.
- Warstwa dostępu do danych — otoka wokół warstwy danych, która zapewnia dostęp do danych Create, Read, Update, Delete (CRUD) bez uwidaczniania szczegółów implementacji obiektu wywołującego. Na przykład dal może zawierać instrukcje SQL służące do wykonywania zapytań lub aktualizowania danych, ale kod odwołujący się nie musi tego wiedzieć.
- Warstwa biznesowa — (czasami nazywana warstwą logiki biznesowej lub BLL) zawiera definicje jednostek biznesowych (model) i logikę biznesową. Deseń kandydata na fasadę biznesową.
- Warstwa dostępu do usług — służy do uzyskiwania dostępu do usług w chmurze: od złożonych usług internetowych (REST, JSON, WCF) do prostego pobierania danych i obrazów z serwerów zdalnych. Hermetyzuje zachowanie sieci i udostępnia prosty interfejs API, który ma być używany przez warstwy Aplikacji i interfejsu użytkownika.
- Warstwa aplikacji — kod, który jest zwykle specyficzny dla platformy (nie jest ogólnie udostępniany na różnych platformach) lub kod specyficzny dla aplikacji (zwykle nie do wielokrotnego użytku). Dobrym testem, czy umieścić kod w warstwie aplikacji, a warstwą interfejsu użytkownika jest (a), aby określić, czy klasa ma jakiekolwiek rzeczywiste kontrolki wyświetlania, czy (b) może być współużytkowany między wieloma ekranami lub urządzeniami (np. i Telefon iPad).
- Warstwa interfejsu użytkownika — warstwa interfejsu użytkownika, która zawiera ekrany, widżety i kontrolery, które nimi zarządzają.
Aplikacja może niekoniecznie zawierać wszystkie warstwy — na przykład warstwa dostępu do usług nie istnieje w aplikacji, która nie uzyskuje dostępu do zasobów sieciowych. Bardzo prosta aplikacja może scalić warstwę danych i warstwę dostępu do danych, ponieważ operacje są bardzo podstawowe.
Typowe wzorce oprogramowania dla urządzeń przenośnych
Wzorce to ustalony sposób przechwytywania cyklicznych rozwiązań typowych problemów. Istnieje kilka kluczowych wzorców, które są przydatne do zrozumienia w tworzeniu utrzymywania/zrozumiałych aplikacji mobilnych.
- Model, View, ViewModel (MVVM) — wzorzec Model-View-ViewModel jest popularny w strukturach, które obsługują powiązanie danych, takie jak Xamarin.Forms. Został on spopularyzowany przez zestawy SDK z obsługą języka XAML, takie jak Windows Presentation Foundation (WPF) i Silverlight; gdzie model ViewModel działa jako przejście między danymi (model) i interfejsem użytkownika (Widok) za pomocą powiązania danych i poleceń.
- Model, Widok, Kontroler (MVC) — typowy i często niezrozumiany wzorzec MVC jest najczęściej używany podczas kompilowania interfejsów użytkownika i zapewnia rozdzielenie rzeczywistej definicji ekranu interfejsu użytkownika (widok), aparatu obsługującego interakcję (kontroler) i danych, które go wypełniają (model). Model jest w rzeczywistości całkowicie opcjonalnym elementem i dlatego podstawą zrozumienia tego wzorca jest widok i kontroler. MVC to popularne podejście do aplikacji systemu iOS.
- Fasada biznesowa — wzorzec AKA Manager zapewnia uproszczony punkt wejścia do złożonej pracy. Na przykład w aplikacji Do śledzenia zadań może istnieć
TaskManager
klasa z metodami takimi jakGetAllTasks()
,GetTask(taskID)
,SaveTask (task)
, itp. KlasaTaskManager
zapewnia fasadę wewnętrzną pracy rzeczywistego zapisywania/pobierania obiektów zadań. - Singleton — wzorzec singleton zapewnia sposób, w jaki tylko pojedyncze wystąpienie określonego obiektu może kiedykolwiek istnieć. Na przykład w przypadku korzystania z biblioteki SQLite w aplikacjach mobilnych potrzebujesz tylko jednego wystąpienia bazy danych. Użycie wzorca Singleton jest prostym sposobem zapewnienia tego.
- Provider — wzorzec ukuty przez firmę Microsoft (prawdopodobnie podobny do strategii lub podstawowego wstrzykiwania zależności), aby zachęcić do ponownego użycia kodu w aplikacjach Silverlight, WPF i WinForms. Kod udostępniony można zapisywać względem interfejsu lub klasy abstrakcyjnej, a konkretne implementacje specyficzne dla platformy są zapisywane i przekazywane w momencie użycia kodu.
- Async — nie należy mylić ze słowem kluczowym Async, wzorzec asynchroniczny jest używany, gdy należy wykonać długotrwałą pracę bez konieczności przechowywania interfejsu użytkownika lub bieżącego przetwarzania. W najprostszej formie wzorzec asynchroniczny po prostu opisuje, że długotrwałe zadania powinny być uruchamiane w innym wątku (lub podobne abstrakcje wątku, takie jak zadanie), podczas gdy bieżący wątek nadal przetwarza i nasłuchuje odpowiedzi z procesu w tle, a następnie aktualizuje interfejs użytkownika, gdy zwracane są dane i stan.
Każdy z wzorców zostanie zbadany bardziej szczegółowo, ponieważ ich praktyczne zastosowanie zostało zilustrowane w badaniach przypadków. Wikipedia zawiera bardziej szczegółowe opisy wzorca MVVM, MVC, fasady, singleton, strategii i dostawcy (i wzorców projektowych na ogół).