Zawartość warstwy Model w implementacji aplikacji Dietphone « Pabloware + Windows Phone

Pabloware + Windows Phone

Niezależny blog firmy Pabloware o systemie Windows® Phone 7

Zawartość warstwy Model w implementacji aplikacji Dietphone

Aplikacja została skonstruowana zgodnie z opisanym w poprzednich wpisach wzorcem architektonicznym MVVM, ale ograniczymy się tutaj do opisu jedynie warstwy Model aplikacji. Ponadto w następnym wpisie zostaną opisane autonomiczne fragmenty kodu, które mogą mieć zastosowanie w innych aplikacjach na system Windows Phone 7.

Calculator

Klasa ta służy do obliczania wartości odżywczych na podstawie zawartości składników odżywczych. Motywacją do jej utworzenia było wydzielenie kodu, używanego w wielu miejscach modelu, do jednej klasy. Obliczanie wartości odżywczych, samo w sobie, jest oczywiście bardzo proste i wygląda następująco (jednostką wejściową są gramy):

Obliczanie wartości odżywczych

Category i MealName

Klasa Category to kategoria, do której obecnie mogą być przypisane tylko produkty. Zaś klasa MealName to nazwa posiłku (np. „śniadanie”). Obie klasy są encjami.

DefaultEntities

Jest to interfejs dostarczający domyślnych encji. Obecnie obsługiwane są encje: nazwa produktu i produkt. Domyślne encje używane są, gdy danej encji nie można znaleźć lub po prostu jej nie określono. Wynika to z zasady projektowej unikania, w takich sytuacjach, wartości null.

Entity i EntityWithId

Entity, to podstawowa klasa encji, która pamięta swojego właściciela we właściwości Owner. Dla bezpieczeństwa, jest to właściwość jednorazowego zapisu i chronionego odczytu.

Klasa EntityWithId, to zgodnie z nazwą, klasa Entity, wzbogacona o identyfikator (typu GUID). Większość encji z niej dziedziczy. Klasa ta umożliwiła uogólnienie wyszukiwania encji po ID.

Factories

Jest to najważniejsza część modelu. Ten właściciel wszystkich encji jest kontenerem, zawierającym fabryki poszczególnych typów encji i korzystającym z nich w celach: udostępnienia wszystkich encji, tworzenia nowych encji i zapisu wszystkich encji. Udostępnia, poprzez swoje właściwości, także implementacje interfejsów: Finder oraz DefaultEntities.

Celem utworzenia tego interfejsu była chęć zapewnienia jednego miejsca, z którego można uzyskać dostęp do całego modelu. Ponieważ każda encja zna obiekt implementujący ten interfejs (swojego właściciela), może ona poruszać się po całym modelu i jest samowystarczalna. To duża zaleta.

Implementacja nie jest klasą statyczną, ani nie wymusza wzorca singletonu, choć obecnie jest tworzona w aplikacji tylko raz. Jest przekazywana do warstwy ViewModel podczas tworzenia tejże, umożliwiając jej komunikację z warstwą Model. Taka strategia tworzenia ułatwia testowanie aplikacji, izolując komponenty wszędzie, gdzie jest to możliwe.

Factory i FactoryCreator

Factory jest to generyczna klasa fabryki encji. Umożliwia odczyt i zapis encji danego typu oraz utworzenie nowej encji. Do właściwego odczytu i zapisu korzysta z obiektu implementującego interfejs Storage. Ponadto przypisuje właściciela do każdej odczytanej lub utworzonej encji.

Natomiast klasa FactoryCreator tworzy obiekty klasy Factory. Korzysta z klasy StorageCreator, skąd uzyskuje obiekt Storage, który przekazuje do tworzonego obiektu Factory. Klasy FactoryCreator używa implementacja Factories.

Finder i FinderExtensions

Interfejs Finder pozwala przeszukiwać model według różnych kryteriów, w tym według ID. Zaś klasa FinderExtensions zapewnia generyczne rozszerzenie (cecha języka C#) każdej listy encji zawierających ID o metodę szukania encji po ID. Korzysta z niej implementacja Finder.

Meal

Jest to encja reprezentująca posiłek. Zawiera listę składników posiłku (czyli obiektów MealItem), które udostępnia na zewnątrz jako ReadOnlyCollection (typ .NET). Umożliwia ich dodawanie, usuwanie, a także jednorazową inicjalizację całej listy oraz kopiowanie jej z innego posiłku. Potrafi również obliczyć swoją wartość odżywczą i udostępnia walidację.

MealItem

MealItem jest encją reprezentującą składnik posiłku. Jest to końcowa klasa, której funkcjonalność budowana jest w następujących, kolejno po sobie dziedziczących klasach:

  1. MealItemBase – pozwala określić: produkt, ilość i jednostkę, a więc w pełni określić składnik posiłku. Referencja do produktu jest pamiętana po jego odnalezieniu.
  2. MealItemWithNutrientsPerUnit – oblicza ilość składników odżywczych i wartość odżywczą w określonym produkcie, przypadających na pojedynczą określoną jednostkę (lub porcję).
  3. MealItemWithNutrients – oblicza ilość składników odżywczych i wartość odżywczą, przypadających na cały składnik posiłku.
  4. MealItemWithValidation – udostępnia walidację.

Pomocnicza klasa UnitUsability sprawdza dostępność informacji o składnikach odżywczych na jednostkę produktu, dla klas: MealItemWithNutrientsPerUnit i MealItemWithValidation.

Product i UnitAbbreviations

Encja Product reprezentuje produkt spożywczy. Potrafi obliczyć niektóre swoje składniki odżywcze i wartość odżywczą oraz je wszystkie przechowuje. Udostępnia również walidację.

Natomiast klasa UnitAbbreviations konwertuje jednostki ilości produktu na tekst i odwrotnie.

Storage, StorageCreator i StorageBuilder

Storage, to generyczny interfejs odczytywania i zapisywania list encji, który jest implementowany poza modelem. Natomiast StorageCreator, to generyczny interfejs tworzenia obiektów Storage (generyczna fabryka abstrakcyjna). Również jest implementowany poza modelem. Jego implementacja jest jedynym obiektem przekazywanym do implementacji Factories podczas jej tworzenia.

Interesująca jest klasa StorageBuilder, stosowana przez obiekty StorageCreator i służąca do automatycznego wybierania właściwej, dla danego typu encji, implementacji Storage. Zostanie ona omówiona, przy okazji jej wykorzystania, w następnym wpisie.

No Responses to “Zawartość warstwy Model w implementacji aplikacji Dietphone”

Kanał RSS z komentarzami do tego wpisu. TrackBack URL

Leave a Response