Trochę o szkoleniu młodzieży

Właśnie zdałem sobie sprawę, że niedawno minęło 10 lat od kiedy zacząłem moją przygodę z programowaniem. Przypominam sobie od czego ja zaczynałem i na samą myśl o kodzie, który wtedy tworzyłem pojawia się uśmiech na mojej twarzy 🙂

Jako młodzi programiści na początku zawsze popełniamy błędy i często podążamy niewłaściwą drogą. Jak zatem poradzić sobie na początku, na co zwrócić szczególną uwagę, a czego się wystrzegać?

Na początek odpowiedzmy sobie na pytania, dlaczego pomimo tego, że w dużej mierze nasze projekty nie są jakieś strasznie skomplikowane i głównie polegają na odebraniu jakiś danych z formularza użytkownika, zwalidowaniu poprawności i zapisaniu w jakiejś bazie danych. To dlaczego większość z tych projektów kończy się klęską albo w najlepszym przypadku strasznym skomplikowaniem? Każdy kto przejmuje ten kod w utrzymanie zaczyna przeklinać…?

To co pierwsze przychodzi mi do głowy to skłonność do nadmiernego kopiowania cudzych rozwiązań. Metoda copiego pasta? Pomijam już takie przypadki, które zdarzyło mi się niestety widzieć w swojej karierze jak skopiowana metoda mająca 1000 linijek, wklejona pod spodem, a w niej zmieniona jedna linijka i jeden parametr – tego chyba nie trzeba komentować… Ucząc się programować czy to w ogóle szukając rozwiązań problemów korzystamy z dobrodziejstw Internetu. No i niestety często zdarza się, że kopiowane są rozwiązania bez przemyślenia jak to się wpisuje w aplikację, którą tworzymy, jaki ma to wpływ na architekturę? Moja rada jest taka, jeśli już kopiujemy jakieś rozwiązanie, spróbujmy je napisać po swojemu, coś pozmieniać, uruchomimy być może w ten sposób proces myślowy, który doprowadzi nas do lepszego rozwiązania? To samo tyczy się tzw. kodu legacy, który otrzymujemy w spadku w utrzymanie, często zdarza się, że nie zastanawiamy się nad tym jak to jest zrobione, wychodzimy z założenia, że skoro działa to po co coś zrobić lepiej, a często jeszcze bardziej bałaganimy… Jeśli jesteśmy na początku swojej przygody z programowaniem, nie róbmy tak, w ten sposób nie uczymy się niczego nowego, tylko stajemy się bezmyślnymi koderami, zawsze każde własne rozwiązanie, nawet jeśli jest niedoskonałe ale było próbą zrobienia czegoś lepiej to dobry pomysł – dzięki temu zdobywamy cenne doświadczenie.

Druga sprawa to nadmierne przywiązywanie się do frameworków i buzzwordów, tak sam pamiętam swoją fascynację MVC, po prostu musiałem tego gdzieś użyć, nieważne co to za projekt czy klient chce aplikację desktopową – musi być przy użyciu MVC. Jasne, że frameworki i różnego rodzaju fajne nowinki zawsze będą nas najbardziej kręcić, w końcu jesteśmy programistami, czyli osobami technicznymi i technologia zawsze będzie nas najbardziej kręcić. Po prostu zachowajmy umiar, nie starajmy się na siłę wciskać rozwiązań tylko dlatego, że są fajne albo modne. Co z tego, że nasza aplikacja jest napisana w Angularze, przy użyciu EntityFramework i SignalR skoro działa wolno i nie spełnia wymagań biznesu? W tej branży chodzi o to aby dostarczyć klientowi rozwiązanie jakiego potrzebuje, biznes nie potrzebuje frameworków, biznes chce zarabiać pieniądze, frameworki mają nam pomóc osiągnąć ten cel.

Jeśli Uncle Bob się nie myli pisząc na swoim blogu, że co 5 lat liczba programistów się podwaja to przed senior developerami, dev leadami, architektami stoi niezłe wyzwanie. Jak ogarnąć młodzież, jak sprawić, aby czerpali radość z poszukiwania rozwiązań, aby chcieli się uczyć nie tylko nowych frameworków ale też wzorców projektowych i dobrych praktyk. Jeśli jesteś starym wyjadaczem, guru czy zwał jak zwał to właśnie przed Tobą stoi największe wyzwanie. To Ty musisz być wzorem do naśladowania, ale Twoim zadaniem nie jest tylko nadawanie kierunku projektu i określania żelaznej architektury, którą robiłeś już setki razy. Jeśli sam nadal programujesz to dobrym pomysłem będzie, aby Ci ludzie poznali procesy myślowe, które doprowadziły do końcowego rezultatu, może wykorzystać do tego celu code review? Twoją najważniejszą misją powinno być przekonanie tych ludzi do ciągłej nauki, do szukanie samodzielnie rozwiązań, tak aby czerpali z tego co robią satysfakcję.

SMessaging – prosta architektura oparta o wiadomości

Nie ukrywam, że od dawna podoba mi się podejście do budowy aplikacji w oparciu o wiadomości. Zdecydowałem się zebrać wszystkie mi znane materiały i napisać prosty framework (przynajmniej narazie prosty), którego zadaniem będzie umożliwienie budowy aplikacji w oparciu o wiadomości i handlery.

Dzięki temu w łatwy sposób możemy w naszej aplikacji zaimplementować CQRS ale nie tylko. W internecie można znaleźć bardzo wiele implementacji tego patternu ale ja chciałem maksymalnie uprościć architekturę, przecież nie zawsze nasza aplikacja musi być tak skomplikowana aby implementować odrazu CQRS.

Kod zarówno frameworka jak i przykład wykorzystania w aplikacji znajdziecie na GitHubie. Przedstawię w skrócie przykładową implementację w oparciu o prosty system rezerwacji.

Zaczynamy od kontrolera WebAPI, gdzie wstrzykujemy interfejs IMessaging:

To jest już pierwsza równica w budowaniu aplikacji w oparciu o wiadomości. Tradycyjnie tu mielibyśmy jakiś serwis aplikacyjny lub odrazu repozytorium dostępu do DB i w metodach robili jakieś operacje CRUD. Natomiast w tym podejściu zawsze do kontrolera będzie wstrzykiwany jeden interfejs, którego zadaniem jest przekazanie wiadomości przychodzącej „gdzieś” dalej, a przecież każdy request od użytkownika, każdy json, który leci do naszego API to tak naprawdę jakaś wiadomość, np. CreateOrder, GetOrder czy ShowListOfCars.

W takim podejściu nie ważne czy implementacja jest w serwisie, czy może w zupełnie innym miejscu. Bardzo upraszcza to kontroler WebAPI, jego odpowiedzialność to teraz tylko odebrać wiadomość, przekazać ją dalej i obsłużyć wynik lub ewentualny wyjątek:

Czy nie jest prościej?

Obsługę wiadomości implementujemy w handlerze, w dowolnym miejscu naszej aplikacji:

Zadaniem handlera jest wykonać daną operację i zwrócić wynik w postaci bardzo prostej struktury MessageResult. Dla operacji typu command czyli takich, które zmieniają stan aplikacji będzie to wyglądało podobnie ale wynik nie będzie potrzebny:

W taki sposób nasza aplikacja właściwie „sama” implementuje część patternów CQRS, stosując podejście handler per wiadomość właściwie w naturalny sposób odeseparowywujemy wiadomości pobierające dane od zmieniających stan aplikacji.

Aby włączyć framework należy go dodać w klasie konfigurującej zależności, w przypadku ASP.NET Core w klasie Startup:

To chyba tyle jeśli chodzi o prosty przykład. W przyszłości planuję rozwinąć framework o obsługę prostej kolejki i możliwość przesyłania wiadomości po sieci tak aby możliwe było zbudowanie rozproszonego systemu. Zapraszam do pobierania kodu z GitHuba.

Framework jest również dostępny do pobrania w NuGet.

 

Testy DB przy użyciu EntityFramework Core

Tak zgadza się, ten post będzie o testowiu warstwy dostępu do bazy danych. Pewnie zadajesz sobie pytanie po co testować bazę danych. Zgadzam się z tym w pełni w wielu przypadkach nie ma takiej potrzeby… Przecież można stworzyć interfejs, który w teście zamockuję i po sprawie…Tak to prawda w wielu przypadkach takie podejście będzie wystarczające ale co jeśli np. otrzymaliśmy w spadku system legacy i nie ma czasu na refactor całego rozwiązania, a chcemy napisać test integracyjny kontrolera MVC / WebAPI czy serwisu WCF.

Jeśli do tej pory używaliśmy EntityFramework czy jakiegoś innego Frameworka w naszej aplikacji to pewnym problemem podczas próby napisania testu był stan naszej aplikacji inaczej mówiąc dane jakie mamy w bazie danych. Pojawiało się pytanie czy podczas uruchamiania testów wykonywać je na specjalnym środowisku, utrzymywać specjalną bazę danych tylko pod testy, generować dane pod testy i na końcu sprzątać po sobie, może test uruchamiać w traksakcji… Wszystkie te czynności zajmowały dużo czasu….

I tu z pomocą przychodzi EntityFrameworkCore i InMemory provider dzięki, któremu możemy nasze testy uruchamiać niezależnie od bazy danych, a zarazem testować operacje CRUD na danych.

Jeśli używasz w swoich aplikacjach pełnego „starego” .NET, i nie masz możliwości użyć .NET Core nie kończ proszę czytać w tym miejscu. Ponieważ EF Core możesz uruchomić w normalnej aplikacji .NET i zaraz pokażę jak…

Na początek tworzę normalny projekt ASP.NET WebApi, jedyne wymaganie do wybranie docelowego frameworka minimum w wersji 4.6.1.

Dodajmy teraz paczkę Nuget dla EF Core, w tym celu instaluję paczkę Microsoft.EntityFrameworkCore.SqlServer ponieważ w projekcie WebAPI chcę użyć SQL Server.

Dzięki biblioteką .NET Standard możliwe jest pisanie aplikacji, które możemy uruchomić w dowolnym środowisku .NET, nie inaczej jest z EF Core!

Właściwie jeśli chodzi o podejście nic się nie zmieniło pomiędzy EF 6 a EF Core (EF Core to tak naprawdę EF 7), definiujemy klasę dla naszego kontekstu i używamy DbSet dla obsługi poszczególnych encji. Jedyna różnica to sposób w jaki konfiguruje się parametry połączenia, wcześniej przekazywało się connectionString poprzez kontruktor. Teraz przekazuje się DbContextOptions i korzysta się z DbContextOptionsBuilder do konfiguracji tego np. we frameworku Dependency Injection.

Użycie kontekstu w aplikacji praktycznie niczym się różni:

Przejdźmy teraz do testów. Aby umożliwić użycie EF Core i providera InMemory należy zainstalować paczkę  Microsoft.EntityFrameworkCore.InMemory.

Dzięki temu w naszym teście możemy skonfigurować DbContext tak aby wszystkie operacje były wykonywane w pamięci. Prosty test sprawdzający czy dane prawidłowo zostały zapisane w bazie danych wygląda następująco:

Celowo dodałem bloki using aby zobrazować potencjał jaki drzemie w tego typu podejściu. Moglibyśmy spreparować odpowiedni DbContext i uruchamiać na nim całą serię testów naszych CRUD-ów. Zawsze gdy tworzony jest nowy kontekst bazy danych EF korzysta wewnętrznie z cache i dane, które już zapisaliśmy są dostępne zupełnie jak byśmy korzystali z bazy danych!

Podsumowując myślę, że naprawdę warto się zastanowić nad wykorzystaniem tego Frameworka, koszt przejścia z wersji EF 6 do EF Core nawet jeśli korzystamy ze „starego” .NET nie powinien być duży. Dzięki temu możemy zaoszczędzić sporo czasu i już nie zastanawiać się jak zapewnić prawidłowe dane pod testy.

ShopHelper – Unit testy

Poprzedni wpis na temat projektu ShopHelper: lokalna lista zakupów

No i przyszedł czas na testy jednostkowe. Być może trochę późno powiedzą fani TDD 🙂 Ogólnie dodając pierwsze komponenty starałem się mieć gdzieś z tyłu głowy, że będę testy pisał ale jak to bywa nie wszystko się odrazu wie… Ten wpis będzie tak naprawdę o dostosowaniu projektu do testów jednostowych i małym refactorze, który musiałem zrobić aby móc testować 🙂

Pierwszy być może mały błąd popełniłem decydując się na SharedProject zamiast Portable class library. Dlaczego?

Rozwiązaniu typu SharedProject kompiluje się razem z binarką, do której został dołączony, oznacza to, że tak naprawdę nasz kod nie kompiluje się do samodzielnej biblioteki. Wyjścia są dwa, a może i nawet trzy. Pierwsze dodać po projekcie do każdej platformy czyli Android.Tests, UWP.Tests, iOS .Tests – masakra. Drugie dodać sztuczną bibliotekę typu portable, do której dołączymy nasz SharedProject, następnie tą bibliotekę podłączymy do naszego projektu z testami. Trochę sztuka dla sztuki ale powinno się udać. Zdecydowałem się na trzecie rozwiązanie – zwykłe klasyczne windowsowe class library (oczywiście jeśli ktoś programuje na Mac-u to rozwiązanie odpada). Problem jaki wynika z tego rozwiązanio to tak naprawdę to, że nasz kod musi obsługiwać tak naprawdę platformę Windows Desktop…  Spowodowało to konieczność wydzielenia poszczególnych implementacji komponentów specyficznych dla danej platformy, jak np. ścieżki do plików. Zaimplementowałem to tak, że we wspólnym kodzie dodałem interfejs IFileService (wcześniej korzystałem ze statycznego Utils-a). W natywnych projektach dla każdej z platform dodałem po klasie implementującej ten interfejs (również do projektu z testami).

Przykład dla Androida:

Kolejny typowy problem, który się pojawił to, że nie wstrzykiwałem zależności do komponentów oraz nie korzystałem z interfejsów co utrudnia Mockowie. Jak napisać test sprawdzający czy wywołano metodę Show, która ma pokazać komponent listy?

Raczej się nie da, pomijając już, że metoda jest prywatna ale taka miała być ponieważ jest podpięta to Command, więc test planowałem wykonać porzez Command.Execute(null). Jednak to się też nie uda ponieważ nie wstrzykuję ani Command ani ViewModel-u, który trzyma Command… Zrobiłem refactor tego komponentu no i udało się osiągnąć zamierzony efekt 🙂

Kod jest prosty, a zarazem napisanie testu sprawdzającego czy komenda ShowShoppingListCommand otwiera komponent ShoppingList to formalność.

Do obsługi testów skorzystałem z Framework-a NUnit oraz Moq. Natomiast sam test jest napisany zgodnie ze wzorcem Arrange-Act-Assert co pozwola na czytelne formatowanie kodu testów. W sekcji arrange umieściłem kod odpowiedzialny za stworzenie obiektów potrzebnych do przeprowadzenia testu. Sekcja Act to tylko wywołanie testowanego polecenia. Assert sprawdza czy na Mock-u wykonano dokładnie raz metodę Show. Jak pewnie zauważyłeś testy wymusiły na mnie dodanie interfejsów również dla widoków, dzięki czemu w testach nie korzystam z prawdziwych widoków tylko mockuje interfejs, dzięki czemu testy są zupełnie odseparowane od warstwy prezentacji.

Na koniec tego wpisu jeszcze inny przykład testu:

Test ma za zadanie sprawdzić czy polecenie AddShoppingListItem wykonuje dodanie elementu do usługi przechowującej dane oraz czy element jest dodawany do listy bindowanej do widoku. Na koniec czy wartość NewShoppingListItemValue jest czyszczona. Przy okazji zacząłem się zastanawiać czy nie zacząć utrzymywać kolekcji ObservableCollection, która jest bindowana do widoku tylko w serwisie.

Właśnie na tym polega magia testów jednostkowych, testy nie tylko pomagają znaleźć błędy ale jeśli zastosujemy technikę TDD to pomagają pisać lepszy kod! Warto już na początku projektu zacząć pisać testy, dzięki temu unikniemy późniejszych bolesnych zmian. Oczywiście refator to powinna być nieodłączna czynność w TDD ale warto już na starcie przygotować nasz projekt tak aby był łatwo testowalny:

  • zapewnić odpowiednią abstrakcję poprzez interfejsy tam gdzie będziemy chcieli skorzystać z Mocków
  • generalnie nie twórzmy samodzielnie zależności tylko wstrzykujmy je z zewnątrz, np. poprzez konstruktor jako abstrakcję
  • jak najmniej starajmy się korzystać ze statycznych Utilsów, Helpersów itp. ponieważ zmockowanie takiej metody jest bardzo trudne, nawet zamiast DateTime.Now zalecałbym jakiś interfejs albo własny obiekt, który na potrzeby testu można podmienić

To chyba na dziś wszystko, zapraszam do komentowania 🙂 Pełny kod znajdziesz na GitHubie.

ShopHelper – lokalna lista zakupów

Poprzedni wpis na temat projektu ShopHelper: Pierwsze kroki i trochę o MVVM

W tym wpisie chciałbym napisać trochę o przechowywaniu danych listy zakupów. Na tą chwilę zdecydowałem się zrobić to jak najprościej, tj. dane będę zapisywał do lokalnego json-a. Na razie nie potrzebuję zarówno serwera jak i nawet lokalnej bazy danych, być może w przyszłości tak ale teraz chcę uruchomić jak najprostrzą funkcjonalność.

Przejdźmy teraz do implementacji, dodałem klasę ShoppingListService, która będzie odpowiedzialna za zapis nowych elementów listy zakupów oraz odczyt listy – czyli poprostu CRUD.

Generalnie chodzi o to aby na urządzeniu mobilnym trzymać gdzieś nasze dane w pliku, myślę, że na tą chwilę wykorzystanie np. SqlLite byłoby nadmiarowe. Do przechowywanie i późniejszej serializacji / deserializacji wykorzystałem prostą klasę ShoppingListData:

Aby zapewnić prostą i szybką serializację / deserializację obiektów dodałem do projektu chyba najpopularniejszą bibliotekę w świecie .NET czyli Newtosoft.Json. Poniżej obsługa ładowania i zapisywania danych z pliku json:

Jak pewnie już zauważyłeś nasz serwis nie zapewnia jeszcze żadnego publicznego API do pobierania listy i dodawania nowych elementów. Jednak dzięki poprzedniej wewnętrznej implementacji API to już formalność 🙂

Pozostało mi już tylko zaprezentować jak komponent listy korzysta z nowo dodanego serwisu. Z pobierania danych korzysta metoda odpowiedzialna za odświeżanie listy.

Efekt jest taki jaki chciałem osiągnąć cała lista jest przechowywana lokalnie na urządzeniu mobilnym. Czyli pomału można zacząć korzystać z aplikacji… No dobra może jeszcze trochę brakuje 🙂

Myślę, że przedstawione rozwiązanie może się przydać wszystkim osobom, które nie potrzebują relacyjnej bazy danych ponieważ chcą zapisywać proste dane albo całe grafy obiektów. Bardziej  spostrzegawczy pewnie już zauważyli, że można łatwo przerobić ten serwisik do wersji generycznej. Kod źródłowy oczywiście znajdziecie na GitHubie.

 

CrossPlatform Logger

Dziś chciałbym pokazać jak zaimplementować prostego loggera na platformie Xamarin.Forms. Nie znalazłem żadnego dedykowanego rozwiązania oferowanego przez twórców tego Frameworka więc stworzymy dziś bardzo prosty logger,  który pozwoli na logowanie do pliku.

Zaczynamy od utworzenia prostego interfejsu ILogger oraz jego generycznej wersji, która będzie służyć do definiowania kategorii na podstawie typu.

Do zdefiniowania poziomów logowania wykorzystam prostego enuma.

Stworzę teraz klasę FileLogger,  aby umożliwić logowanie na każdej z platform użyje najprostszego mechanizmu, statycznej metody File. AppendAllText. Natomiast odpowiedzialność za tworzenie ścieżki do pliku oraz samej wiadomości przenoszę w inne miejsce za pomocą delegatów. W ten sposób mamy uniwersalny mechanizm,  który możemy wykorzystać na wielu platformach.

Jak widać powyżej pojawił się jeszcze jeden typ LogItem, jest to prosta struktura, która zastąpi przekazanie wielu parametrów do delegatów zgodnie z zasadą, że im mniej parametrów tym lepiej.

Odpowiedzialność za tworzenie ścieżki do pliku oraz samej wiadomości umieściłem w FileLoggerFactory. Klasa ta ma za zadanie stworzyć katalog gdzie zapisywane będą logi oraz zdefiniować delegaty. Oczywiście samo generowanie ścieżki oraz wiadomości jest bardzo proste i niekonfigurowalne, pozostawiam decyzję Tobie czy chcesz użyć jakiejś innej własnej implementacji.

Tak zbudowane rozwiązanie możemy zarejestrować w dowolnym kontenerze Dependency Injection. Jedyne o czym należy pamiętać to, że definicja katalogu gdzie przechowywane będą logi będzie różna dla każdej z platform, poniżej mały przykład z użyciem symboli kompilacji dla różnych platform.

To chyba właściwie wszystko jeśli chodzi o uniwersalne logowanie do pliku dla Androida, iOS-a i UWP przy użyciu framework-a Xamarin.Forms. Każda z platform dostarcza również natywne sposoby logowani ale to nie było celem tego wpisu. Jeśli chcesz dodaj kolejną implementację ILogger, np. AndroidUtilLogger i wykorzystaj Android.Util.Log.Info(„MyApp”, „Hello”).

Cały kod z przykładów znajdziesz na GitHubie.

ShopHelper – Pierwsze kroki i trochę o MVVM

Poprzedni wpis na temat projektu ShopHelper: Start

W tym artykule chciałbym zaprezentować pierwszą implementację komponentów UI. W poprzednim poście zakończyliśmy na założeniu solucji i dodaniu domyślnych komponentów z użyciem frameworka Xamarin.Forms. Naszym celem na tym etapie jest:

  • stworzenie podstawowych wspólnych komponentów z użyciem wzorca MVVM (Model-View-ViewModel)
  • zapewnienie podstawowej nawigacji
  • wyświetlenie prostej listy zakupów z możliwością dodawania nowych elementów.

Zaczynamy od stworzenia dwóch klas i jednego interfejsu, które pomogą nam modelować komponenty według wzorca MVVM, oczywiście nie jest to wymagane ale bardzo uspójni architekturę i implementację przyszłych komponentów aplikacji. Tak więc tworzymy interfejs IView:

Interfejs ten jak widać powyżej zawiera tylko jedną właściwość BindingContext, która zapewni  „połączenie” pomiędzy widokiem, a ViewModel. Generalnie interfejs ten powinny implementować wszystkie widoki naszej aplikacji. Czym są widoki? To nic innego jak graficzne komponenty, które udostępnia nam framework Xamarin.Forms, może to być m.in. ContentPage, ContentView lub inne kontrolki… Następnie dodajmy klasę abstrakcyjną ViewModel oraz generyczny ViewModel:

Przedstawiony ViewModel posłuży nam do implementacji bazowego mechanizmu eksponującego model dla widoków. Mówiąc inaczej to w tym miejscu (w klasach pochodnych) znajdą się właściwości, które chcemy udostępnić do warstwy prezentacji. ViewModel implementuje interfejs INotifyPropertyChanged, za pomocą tego interfejsu możemy powiadomić widok, że jakaś wartość jednej z naszych właściwości uległa zmianie. Dzięki takiemu rozwiązaniu otrzymujemy rozdzielenie warstwy prezentacji (widoków) od modelu / logiki. I tak zadaniem widoku jest wyłącznie prezentować dane, nie wykonuje on żadnej logiki.

Przejdźmy teraz do stworzenia podstawowych elementów naszej aplikacji. Każda aplikacji musi mieć jakiś główny komponent, nazwę go po prostu Main. Tworzę więc katalog Main i umieszczam w nim klasę MainComponent, to tu umieszczę logikę związaną z tym komponentem, myślę tu głownie o nawigacji do innych komponentów aplikacji. W tym samym katalogu tworzę MainView.xaml używając szablonu oferowanego przez Visual Studio.

Tak jak wspomniałem wcześniej każdy widok powinien implementować interfejs IView:

Dzięki temu, że ContentPage dziedziczy po BindableObject, w którym już znajduje się właściwość o tej samej nazwie nic więcej nie musimy implementować. W konstruktorze naszego bazowego ViewModel wykona się cała „magia” MVVM – ViewModel zostanie powiązany z widokiem. Następnie utworzyłem klasę MainViewModel, która dziedziczy po generycznym ViewModel. Zwróćmy uwagę jak ViewModel udostępnia informacje do widoku, zobaczmy na właściwości Title oraz ShowShoppingListCommand udostępniane przez nasz MainViewModel:

Jak widać powyżej w widoku mamy odwołanie do tych właściwości poprzez wykorzystanie mechanizmu Binding (wiązania). Dodałem w MainView również jakąś prostą nawigację, wykorzystałem do tego kontrolkę StackLayout i trzy przykładowe przyciski, pod jeden z nich podpinam właśnie wspomniany wcześniej ShowShoppingListCommand, to nic innego jak implementacja System.Windows.Input.ICommand – komendy, która zapewnia przekazanie wykonania do wskazanej metody. Właściwość ShowShoppingListCommand korzysta z metody udostępnianej przez bazowy ViewModel SetProperty. Zadaniem tej metody jest ułatwić wykorzystanie notyfikacji INotifyPropertyChanged i skrócić kod przypisania nowej wartości do jednej linii. Dzięki takiemu mechanizmowi przypisując wartość naszej właściwości powiadamiamy widok o zmianie.

Nową instancję komponentu Main tworzymy w klasie App zaraz po uruchomieniu aplikacji, do metody Run przekazujemy obiekt Application. W metodzie Run uruchomimy nawigację oferowaną przez Xamarin.Forms dodając nasz widok do globalnej nawigacji. W skrócie MainComponent rozpoczyna nawigację globalną dla całej aplikacji oraz tworzy polecenia definiując metody do nawigowania do innych komponentów.

Teraz czas na komponent ShoppingList czyli naszą na razie prostą listę zakupów. Tworzę katalog ShoppingList, a w nim umieszczam kolejno ShoppingListView, ShoppingListViewModel oraz ShoppingListComponent. Widok listy zakupów przedstawia się następująco:

Dzięki prostemu zastosowaniu kontrolek oferowanych przez Xamarin.Forms umieściłem wszystkie komponenty w StackLayout co pozwoli na rozmieszczenie elementów pod sobą na całym ekranie. Dodałem listę, a pod nią kontrolkę Entry, w której możliwe będzie wprowadzanie nowych pozycji. Obok umieściłem przycisk, którym użytkownik będzie mógł dodawać pozycje do listy. Na razie jest bardzo prosto ale tak miało być :). ShoppingViewModel ma za zadanie eksponować właściwości dla widoku i tak też robi, nic innego się tam nie dzieje:

Tu można zauważyć, że pojawiła się jeszcze jedna klasa, jest to ShoppingListItem, na razie bardzo prosty model. ViewModel udostępnia kolekcję ObservableCollection<ShoppingListItem>, dzięki czemu po każdym dodaniu, usunięciu elementów z kolekcji widok zostanie automatycznie powiadomiony o zmianach.

Zadaniem komponentu ShoppingList jak na razie jest stworzyć wszelkie potrzebne dla widoku powiązania i zapewnić obsługę listy zakupów. Jak na razie obsługujemy tylko dodawanie nowych elementów do listy, dzieje się to w metodzie AddShoppingListItem, która została podpięta do AddShoppingListItemCommand. Tak więc zbieramy wprowadzoną przez użytkownika wartość pola NewShoppingListItemValue, jeśli nie jest pusta to dodajemy nowy element do kolekcji i czyścimy właściwość, czyszcząc w ten sposób kontrolkę Entry.

Na początek to chyba tyle 🙂 wychodzę z założenia, aby iść małymi krokami. Dziś chciałem też napisać trochę o MVVM ponieważ korzystając z Xamarin.Forms po prostu nie wypada inaczej, a dzięki zachowaniu prostych zasad tego wzorca nasza aplikacja będzie dobrze napisana. Cały kod znajdziecie oczywiście na GitHubie.

 

CQRS w prostym wydaniu

Czy CQRS to tylko pattern dla wielkich projektów? Oczywiście jeśli chcielibyśmy wdrożyć wszystkie komponenty, zastosować DDD razem z agregatami, sagami oraz dołożyć do tego jeszcze Event Sourcing to tak, być może byłoby to zbyt dużym skomplikowaniem w szczególności jeśli nasz system to głównie CRUD-y.

Jednak zastanówmy się, w wielu systemach można spotkać wykorzystanie wzorca Repository, który właśnie świetnie sprawdza się przy CRUD-ach. Czy przechowujesz implementację dostępu do encji właśnie w repozytorium? Czy w metodach wykonujących zapytania do bazy wykorzystujesz wiele encji, robisz złączenia itp? Jeśli tak może warto zastanowić się na rozdzieleniem operacji zapisu (Create, Update, Delete) od operacji odczytu? Ile widzieliśmy już metod gdzie LINQ ciągnie się przez kilkadziesiąt linii tworząc niepotrzebne skomplikowanie w naszym kodzie (widziałem też LINQ na 300 linii ale wolałbym o nim nie pamiętać :)). Niejednokrotnie patrząc w profilerze jak wygląda zapytanie wygenerowane przez Entity Framework można się złapać za głowę. Tak jak bardzo lubię EF, tak jestem zdania, że Framework ten nie służy kompletnie do robienia zapytań do bazy danych, owszem jeśli chcemy pobrać dane jednej encji jasne jest to świetne narzędzie ale w innych przypadkach nie jest to odpowiednie rozwiązanie.

Tak więc dlaczego w tak wielu projektach wykorzystuje się Entity Framework również do operacji odczytu danych z bazy. Myślę, że jest to kwestia podejścia albo dla wielu osób może się to wydawać po prostu naturalnym rozwiązaniem. Jednak czy poprawnym? Zróbmy prostą rzecz podzielmy nasze Repository na dwa obiekty, jeden wykorzystujący EntityFramework do zapisu, drugi wykorzystujący czystego SQL-a do odczytu z metodami zwracającymi DTO. Wiem, że SQL przestał być ostatnio w modzie ale spróbujmy moim zdaniem warto :).

Testową implementację wykonam w ASP .NET Core. Aby nie odstraszać do końca czytelników nie będę robił ręcznie mapowań z SQL, wykorzystam do tego małą i przyjemną bibliotekę Dapper. Jest to Micro ORM, czy też jak kto woli Object Mapper. Dapper po dodaniu referencji do naszego projektu rozszerza nam System.Data.IDbConnection o dodatkowe metody, które możemy wykorzystać do wykonywania zapytań do DB. Dzięki czemu w łatwy sposób integruje się z generyczną warstwą dostępu do danych oferowaną przez .NET. Przejdźmy więc do implementacji :).

Na początek tworzę nową klasę, nazwałem ją  testowo ProductQueryService, jako, że na potrzeby artykułu będziemy robić zapytania do jakiś testowych produktów w mojej bazie danych:

W kodzie widać, że wstrzykiwany jest delegat Func, pod którym ukryta jest fabryka połączeń IDbConnection. Oczywiście jeśli chcesz możesz tu wstrzykiwać konkretną fabrykę lub też konkretne połączenie, np. SqlConnection. Tak wygląda konfiguracja w kontenerze Dependency Injection:

Idąc dalej mamy metodę, która zwraca nam kolekcję DTO produktu, a w niej wywołanie widoku SQL z użyciem metody Query dostarczanej przez bibliotekę Dapper, który to automatycznie wykonana za nas mapowanie na DTO, warunek jest jeden nazwy właściwości muszę być identyczne jak nazwy kolumn zwracane z SQL. Jeśli jest taka potrzeba możemy dodać aliasy do kolumn bezpośrednio w SQL-u. Oczywiście trzymanie SQL-a bezpośrednio w kodzie nie jest dobrym pomysłem ale na potrzeby testowe wystarczy, w przyszłości postaram się dodać post o dobrym sposobie trzymanie SQL-i w projekcie :). Widok GetProducts w bazie jest bardzo prosty:

Natomiast samo wywołanie naszego serwisu Query w kontrolerze wygląda tak:

Jak widać wynik zapytania trzeba jeszcze zmapować do odpowiedniej postaci. Jako, że naszym celem jest zwrócić listę produktów wraz z nazwami kategorii dla każdego z produktów trzeba wykonać kilka dodatkowych kroków. Jest to oczywiście pewna niedogodność w porównaniu z np. Entity Framework. Jednak największą zaletą Dappera jest wydajność, według strony https://github.com/StackExchange/Dapper jest prawie tak szybki jak za pomocą SqlDataReader:

Na koniec chciałbym jeszcze pokazać możliwość parametryzacji zapytań. Dodałem przykładową metodę, która na podstawie ID wybierze z naszego widoku tylko rekordy o podanym ID:

Klasa GetProductsById to proste DTO zawierające jedną właściwość. Jak widać powyżej Dapper pozwala na przekazanie obiektu z parametrami, automatycznie przypisując wartości właściwości do parametrów w SQL, warunek jest ten sam nazwy muszą się zgadzać! W SQL-u mamy parametr @Id, który odpowiada właściwości w DTO:

Na sam koniec wywołanie z kontrolera, jak widać nasze DTO jest zmapowane z parametrem podanym w URL:

Oczywiście przedstawiony przykład jest bardzo prosty i ktoś mógłby powiedzieć, że to samo można osiągnąć w EF robiąc dwa razy Include. Jednak to nie o to chodzi. Po pierwsze rozdzielając repozytorium na dwa obiekty rozdzielamy odpowiedzialności. Dzięki czemu np. jeśli będzie potrzeba dodania kolumny nie musimy nic zmieniać w samym modelu Entity. Model warstwy odczytu może żyć niezależnie, być rozwijany przez inny zespół czy też być optymalizowany tylko pod konkretne zapytania. Czy też jeśli będzie taka potrzeba możemy korzystać nawet z osobnej bazy danych!

Myślę, że w każdym nawet małym projekcie warto zastanowić się nad rozdzieleniem warstwy DAL na Command i Query, w przedstawionym przeze mnie przykładzie starałem się pokazać, że nie wymaga to aż takiego dużego nakładu pracy, a dzięki temu zachowujemy porządek w kodzie, jeśli nasz projekt w przyszłości się rozrośnie nic nie stoi na przeszkodzie aby zastosować kolejne z technik CQRS. Przykładowy projekt znajdziecie na GitHubie.

ShopHelper – Start :)

1,2,3 Start… Rozpoczynam udział w konkursie Daj Się Poznać 2017 🙂

Na początek nie mogło zabraknąć oczywiście wpisu na temat założenia projektu oraz tego co w ogóle będzie robił ShopHelper!

ShopHelper będzie aplikacją mobilną, której główną funkcjonalnością będzie lista zakupów. Lista zakupów powinna być łatwo edytowalna tak aby z ekranu głównego można było dodać nowe pozycje i odhaczyć już zakupione. Dodatkową opcją będzie udostępnianie listy pomiędzy różnych użytkowników, tak aby każdy mógł edytować listę. Kolejna opcja to historia zakupów. W maksymalnym streszczeniu narazie chyba tyle, choć jeśli starczy czasu i inwencji może coś się jeszcze fajnego pojawi 🙂

Jako technologię wybrałem .NET i Xamarin. Planuję aby aplikacja była uruchamia na wielu platformach więc zdecydowałem się użyć framework-a Xamarin.Forms, który pozwoli na równoczesne pisanie kodu pod Androida, iOS-a oraz UWP z użyciem xaml-a. Do pracy z kodem wykorzystam Visual Studio 2015 Update 3 w wersji Community. Zaczynamy!

 

Utworzyłem solucję w VS, nazwałem ją ShopHelper, natomiast sam projekt ShopHelper.Client. Na tą chwilę nie planuję innych komponentów niż aplikacja kliencka ale nigdy nic nie wiadomo, więc w przyszłości nie będę musiał robić refactoringu w nazwach projektów.

Do udostępniania kodu pomiędzy platformy użyję SharedProject, jest to o tyle fajne rozwiązanie, że kod źródłowy jest automatycznie kompilowany razem z każdym osobnym projektem każdej z platform.

Oznacza to tyle, że o tym jak ma zostać skompilowany decyduje projekt, do którego dodana została referencja do SharedProject. Jak widać poniżej po utworzeniu solucji mamy jeden projekt typu SharedProject oraz 3 natywne odpowiadające konkretnym platformą. W skrócie kod „wspólny” umieszczony w ShopHelper.Client korzysta z framework-a Xamarin.Forms, następnie każdy z projektów z aplikacją natywną pod każdą z platform  posiada referencję do SharedProject oraz wszystkich potrzebnych bibliotek.

Tak wygląda solucja zaraz po utworzeniu:

Cała „filozofia” współdzielenia kodu pomiędzy różne platformy polega na tym, że każda z platform wykorzystuje wspólny komponent App, ładując go w odpowiedni dla konkretnej platformy sposób. Poniżaj klasa App oraz załadowanie jej przez natywną aplikację Android.

Po skompilowaniu i uruchomieniu aplikacja na razie nic nie robi i wygląda tak na tablecie z Androidem:

Podsumowując dziś udało mi się stworzyć „pusty” projekt, który pozwoli na pisanie kodu pod różne platformy, kod oczywiście udostępniam na GitHubie, w następnych dniach utworzę pierwsze prawdziwe komponenty i podzielę się nimi w następnych wpisach. Ufff jak na pierwszy wpis poszło mam nadzieję nieźle, i że nic istotnego nie pominąłem. Zachęcam do zostawienia komentarzy oraz lektury następnych wpisów już wkrótce!