Wprowadzenie do Sass, czyli jak ułatwić sobie życie z CSS

Trochę to trwało, ale wygląda na to, że powoli zaczynam nabierać tempa z rozwojem projektu. Odrobina wolnego czasu pozwoliła mi na ogarnięcie technologii z których będę korzystał (a gdy chcemy korzystać z nowości, czasem może zająć to dosyć długo). Ostatnio projektowałem wygląd aplikacji za pomocą mockup’ów. Nastała więc pora tchnąc trochę życia w projekt i napisać trochę kodu. Przyznam, że słaby ze mnie designer, więc nie będzie to takie proste. Jeżeli mowa o wyglądzie aplikacji webowej, raczej na pewno pojawi się temat CSS’ów. Nie jest to moja najmocniejsza strona, więc postanowiłem sobie trochę ułatwić ten temat. W tym celu sięgnąłem po Sass.

Logo Sass

Co to jest Sass?

Sass, czyli Syntactically Awesome Style Sheets, to preprocesor języka CSS. Dodaje do niego funkcje, które nie są dostępne w podstawowej wersji CSS. Kod Sass jest kompilowany do zwykłego CSSa. W wyniku tej operacji otrzymujemy więc plik zawierający czysty CSS. Można zadać sobie pytanie: po co go używać, skoro ostatecznie uzyskujemy to samo? Jest takie powiedzenie, mówiące że Nie chodzi o cel, tylko o podróż. No i właśnie, korzystając z Sass podróż ta nie jest tak męcząca… Osobiście z CSS nie miałem aż tak dużo do czynienia. Praca ta polegała głównie na drobnych poprawkach, układaniu elementów etc. Motywy były już zwykle gotowe lub korzystałem z gotowych szablonów. Gdy dużo pracy poświęcamy upiększaniu naszej aplikacji za pomocą CSS, możemy jednak natrafić na wiele drobnych lub bardziej poważnych niedogodności.

Problemy z CSS

Pomine tutaj problemy, których użycie Sassa nie rozwiąże. Każdy, kto pracował z tą technologią miał czasem wrażenie, że żyje sobie własnym życiem. W moim przypadku wynika to zwykle z niewiedzy, ale nie zawsze.
Animowany obrazek satyryczny pokazujące typowe problemy z językiem CSS. Scena z kreskówki Family Guy.
A wracając do problemów, które Sass jest w stanie pomóc rozwiązać, to są to między innymi:

  • Problem z kolorem motywów, gdy w naszych plikach CSS trzeba zmienić jakiś kolor, albo po prostu w wielu miejscach użyć tej samej barwy. Musimy kopiować lub pamiętać o jaki kolor chodzi
  • Duplikacje kodu, gdy wiele elementów będzie miało ten sam styl i musimy powielać go wielokrotnie
  • Nie mamy możliwości zagnieżdżaniastylów, co może powodować problem gdy musimy zmieniać nazwę jakiejś klasy lub identyfikatora. Dodatkowo wpływa to także na przejrzystość kodu
  • Brak możliwości wykonywania obliczeń w naszych stylach, czasem chcemy żeby niektóre wartości były od siebie zależne. Musimy robić to ręcznie, czasem w wielu miejscach
  • Import stylów, który jest obecny, ale powoduje wykonanie kolejnego zapytania do serwera po importowany styl

Sass na ratunek

Tutaj z pomocą przychodzi nam Sass. Daje on gotowe rozwiązania na powyższe problemy. Opowiem o nich w skrócie poniżej. Jak wcześniej wspomniałem, Sass to preprocesor języka CSS, przeglądarki nie wiedzą co z nim zrobić. Najpierw trzeba go przekompilować. Nie będę tego tutaj dokładnie opisywał, ponieważ to jak to zrobimy zależy od technologi w jakiej będziemy pracowali. Na początek polecam poćwiczyć online np. na CodePen. Wystarczy, że wybierzemy jako preprocesor SCSS i możemy zaczynać. Tutaj kolejna uwaga: do wyboru mamy dwie składnie Sassa: klasyczną (Sass), oraz nową (SCSS). W poniższych przykładach używam składni SCSS.

Zmienne

Problemy związanie między innymi z kolorami rozwiązuje dodanie zmiennych:

Dzięki nim jeżeli w wielu miejscach wykorzystujemy te same wartości, w przypadku zmiany możemy je łatwo podmienić. Na zmiennych można wykonywać także operacje. Tutaj dla przykładu nagłówek będzie większy od bazowego tekstu o 10px.

Zagnieżdżanie reguł

Zagnieżdżanie pozwala nam na usunięcie kodu który byłby powielany, oraz dodaje mu przejrzystości.

Dzięki temu zabiegowi na pierwszy rzut oka widać, które elementy są ze sobą powiązane. Dodatkowo elementy font zostały pogrupowane razem, co też wpływa na ich czytelność.

Import

Dyrektywa @import pozwana na modularyzację naszego kodu. Dzięki temu możemy dodać do projektu plik .scss, który zawierać będzie tylko deklarację zmiennych z kolorami. W ten sposób łatwo dodawać różne motywy do naszej aplikacji. Poniżej przykładowy plik z deklaracją zmiennych przechowujących kolory.

Następnie wykorzystujemy import pliku ze zmiennymi.

Dzięki temu że importujemy plik .scss, jako efekt tej operacji otrzymamy jeden plik zawierający całą zawartość obu tych plików. Jeżeli importowalibyśmy plik .css, podczas importu musielibyśmy pobrać plik z serwera, przez co musielibyśmy wysłać kolejne żądanie na serwer.

Dziedziczenie reguł

Kolejna dyrektywa którą chcę przedstawić to @extend. Dzięki niej możemy łatwiej definiować elementy posiadające te same style, różniące się tylko kilkoma szczegółami.

Jako element wyjściowy tej operacji otrzymamy następujący kod CSS:

Jedyne zmiana to dodanie do deklaracji bazowej klasy naszej rozszerzonej implementacji, a na końcu dodanie pozostałej części. Zmiana niewielka, ale taki zapis łatwo pokazuje, że elementy te są ze sobą powiązane w logiczny sposób (pełnią podobną rolę). W przypadku gdy będziemy implementować wiele podobnych elementów, taki zapis jest moim zdaniem o wiele bardziej czytelny.

Powtarzalne reguły

Bardzo potężne narzędzie do jakiego daje nam dostęp Sass to dyrektywa @mixin. Dzięki niej nie będziemy musieli powielać wielokrotnie tego samego kody dla różnych, niepowiązanych ze sobą elementów, które mają jednak wspólne cechy. Przykładowo możliwość dodania zaokrąglonych krawędzi. Można to zaimplementować w następujący sposób:

Taki kod sprawia, że możemy wykorzystać tą samą funkcję (funkcja nie do końca można to nazwać, ale pokazuje o co tutaj chodzi) do zaokrąglania krawędzi. Dodatkowo posiada ona parametr, który może mieć wartość domyślną, dzięki czemu wiele elementów które w różny sposób chcemy zaokrąglić może z niej skorzystać.

Funkcje

Kolejna dyrektywa w arsenale Sass to @function. Dzięki niej możemy wydzielić fragment logiki, który będziemy mogli wielokrotnie użyć.

Dzięki temu oszczędzimy czas na operacje, które będziemy wykonywać wielokrotnie.

Podsumowanie

Nie przedstawiłem wszystkich zalet, jakie niesie ze sobą używanie Sass w naszym projekcie. Jeżeli chcecie dowiedzieć się więcej na ten temat, zapraszam do przejrzenia dokumentacji. Wydaje mi się że warto spróbować, jeżeli ktoś nie miał jeszcze styczności z tego typu technologiami. Na rynku jest oczywiście wiele innych rozwiązań, które pełnią podobną fukncję: LESS, Stylus, PostCSS. Niezależnie od naszego wyboru, wydaje mi się, że zawsze będzie to krok na przód.

Wprowadzenie do Angular 2

Dzisiaj chciałem opisać w kilku punktach najważniejsze cechy frameworka Angular dla użytkowników, którzy nie mieli z nim jeszcze styczności. Na wstępnie trzeba zaznaczyć, że twórcy odeszli od nazwy Angular 2 (głównie z powodu wporwadzenia Semantic Versioning). Od teraz wersje 1.x.x nazywamy AngularJS, a do wydań oznaczonych jako 2.x.x i dalej będziemy używali krótkiej nazwy Angular. Można o tym poczytać tutaj.

Czym jest Angular?

Logo frameworka Angular

Angular to framework służący do rozwijania aplikacji webowych oraz na platformy mobilne. Nie jest to kolejna wersja swojego poprzednika, został napisany całkowicie od nowa. Wersje te nie są ze sobą kompatybilne. Na pierwszy rzut oka widać, że dwójka bardzo różni się od swojego pierwowzoru. Poniżej postaram się przedstawić te różnice i pokazać, że pomimo tego że są to całkiem inne narzędzia, developerzy korzystający z jedynki będą mogli wykorzystać część swojego doświadczenia podczas pracy z nowym wydaniem.

Wybór języka

Twórcy Angulara dają nam wybór w kwestii języka, którym będziemy się posługiwać podczas pisania naszych aplikacji. Do wyboru mamy następujące opcje:

  • ES5, czyli po prostu JavaScript. Ten sam, który był najczęściej wykorzystywany podczas rozwoju aplikacji w starym AngularJS.
  • ES6/ES2015, jest to rozszerzenie standardowego języka JavaScript, dodające nowe funkcje. Nie wszystkie przeglądarki go wspierają, dlatego podczas rozwoju aplikacji wykorzystujących ES6 należy korzystać z kompilatorów np. Babel.
  • TypeScript wprowadza do JavaScript’u jeszcze więcej możliwośći np. typy, dzięki czemu łatwiej wyłapywać błędy podczas pisania aplikacji. Jest rozszerzeniem ES6, i tak samo jak on, wymaga kompilatora. Więcej na jego temat można poczytać w tym miejscu.
  • Dart jest to język programowania stworzony przez firmę Google. Po więcej informacji na temat tego języka zapraszam tutaj.

W dalszej części tego artykuły będę posługiwał się przykładami napisanymi w TypeScripcie.

Moduły

Obie wersje Angulara przedstawiają koncepcję modułu, jako swego rodzaju punkt wejścia dla naszej aplikacji. W pierwszej wersji definiowaliśmy go w następujący sposób:

W nawiasach kwadratowych podawaliśmy zależności z których chcieliśmy korzystać w naszej aplikacji. Następnie musieliśmy oznaczyć w HTMLu gdzie nasza aplikacji ma się znajdować:

Teraz definiujemy go w następujący sposób:

Moduł tym razem służy do oznaczenia z jakich elementów nasza aplikacja będzie się składała. Do tego celu służy dekorator @NgModule, który używamy w połączeniu z klasą modułu. Wskazujemy, z jakich modułów dostarczanych z zewnątrz będziemy korzystać (imports) np. RouterModule lub BrowserModule. Deklarujemy (declarations) z jakich komponentów będziemy korzystać w naszej aplikacji. Może się ona składać z setek lub tysięcy małych komponentów. Definiujemy tutaj także komponent wejściowy przy użyciu słowa bootstrap. Komponent ten zostaje uruchomiony jako pierwszy. W górnej części tego pliku znajdują się importy, czyli mechanizm TypeScriptu, który pozwala na użycie innych bibliotek w naszej aplikacji. Modułom dokładniej przyjrzymy się w kolejnych postach.

Kontrolery i Komponenty

Angular odszedł od koncepcji kontrolerów, używanych w pierwszej wersji. Kontrolery były definiowane w widoku:

Następnie dodawany był kod, który przedstawiał jego logikę.

Obecnie w widoku używamy tylko nazwy naszego komponentu np.:

Sam komponent zaś definiuje jego logikę oraz wygląd:

Importujemy tutaj dekorator komponentu, który pozwala nam na jego definicje. Wskazujemy selector, który będzie wskazywał na nasz komponent w HTMLu, jego wygląd poprzez template (można oczywiście dodać ten szablon w osobnym pliku), oraz logikę komponentu w klasie.

Dyrektywy

Dyrektywy dostępne w Angularze uległy znacznym zmianom, ale dalej są obecne. Popularne w pierwszej wersji dyrektywy to na przykład ng-repeat oraz ng-if. W nowej wersji zostały one zastąpione przez *ngFor oraz *ngIf. Nazywamy je Structural directives, ponieważ wpływają na strukturę naszej strony (powielają elementy, usuwają etc). Są poprzedzane znakiem *. Przykłady dla AngularJS:

A teraz nowa wersja:

Różnice nie są wielkie, oprócz samej składni, dla *ngFor dochodzi także słowo kluczowe let, które definiuje zmienną lokalną.
Oprócz tego, w Angularze usunięte zostają inne dyrektywy, takie jak ng-src, ng-style, ng-href. Podobnie jest z dyrektywami, które służyły do obsługi zdarzeń np. ng-click czy ng-focus. Zamiast tego, możemy podpiąć się bezpośrednio do atrybutów lub zdarzeń w HTML, na przykład:

Do właściwości podpinamy się poprzez nawiasy kwadratowe [], a do zdarzeń nawiasy okrągłe (). Daje nam to dużo możliwości, ponieważ nie musimy już polegać na tym, czy interesująca nas dyrektywa istnieje. Zamiast tego korzystamy po prostu z atrybutów oraz zdarzeń w HTMLu.

Data binding

Tutaj także jest wiele podobieństw, chociaż ponownie składnia trochę się różni. O ile dalej możemy korzystać z nawiasów klamrowych {{...}} aby wyświetlić dane lub tworzyć wyrażenia, to two-way oraz one-way binding znany z poprzednika wygląda trochę inaczej. Działa tutaj ten sam mechanizm, który pokazałem w dyrektywach. One-way binding, w którym zmiany wychodzą z widoku do kodu, odbywa się poprzez użycie nawiasów okrągłych (). Tutaj przykładem mogą być eventy, gdzie zdarzenie wysyła nam informacje do naszej klasy. Wysyłanie danych z klasy do widoku odbywa się poprzez nawiasy kwadratowe [] (wykorzystując atrybuty, klasy, style, właściwości) lub klamrowe {} (mechanizm ten nazywa się Interpolation). Two-way binding, czyli przesył danych w obie strony, odbywa się zarówno przy użyciu nawiasów kwadratowych i okrągłych [(...)]. Składnia ta wydaje się dziwna, ale jest w 100% spójna z tym co powiedzieliśmy wcześniej: dane zarówno wysyłane są z widoku do kodu, oraz z kodu do widoku.

Zamiast nawiasów mamy możliwość korzystania z prefixów bind- lub on- dla komunikacji w jedną stronę, lub bindon- w obie strony. Przykłady:

Serwisy

W pierwszym Angularze mieliśmy do wyboru kilka metod, które pozwalały na dodawanie serwisów do aplikacji. Dzięki nim byliśmy w stanie wyciągnąć w jedno miejsce logikę, która powtarzała się w wielu fragmentach aplikacji lub pozwalały na komunikację pomiędzy różnymi jej elementami. Czasem pojawiał się problem: którą metodę wybrać? Do wyboru były popularne Factory, Service czy Provider, a także Constants oraz Values. Ten element został całkowicie zmieniony w nowej wersji. Zamiast wybierać dostępne mechanizmy, po prostu dodajemy klasę, która ma w sobie określoną funkcjonalność, a następnie używamy jej w dowolnym miejscu.

Należy jedynie dodać dekorator @Injectable, który pozwoli na wstrzyknięcie naszego serwisu np. do komponentu. O tym opowiem w kolejnym akapicie.

Dependency Injection

Dependency Injection to wzorzec architektoniczny, polegający na wstrzykiwaniu zależności do naszego kodu. Jeżeli chcemy odseparować z komponentu logikę np. pobierania użytkowników z bazy danych, a w samym komponencie zająć się jedynie ich wyświetlaniem, możemy zrobić to w łatwy sposób. Pobieranie danych wyciągamy do Serwisu, czyli innej klasy, a w komponencie wskazujemy na to, że potrzebujemy dostać obiekty do wyświetlenia. W module dodajemy komponent i serwis:

W komponencie wskazujemy, że potrzebujemy serwisu (używamy tutaj CatsService z poprzedniego akapitu), który zwróci nam nasze obiekty do wyświetlenia:

W ten sposób nasz komponent będzie w stanie wyświetlić listę naszych kotów, bez wiedzy skąd trzeba je pobrać!

Podsumowanie

Oczywiście, to co tutaj przedstawiłem to tylko część dobrodziejstw które oferuje nam Angular. Mamy jeszcze Routing, który został znacznie uproszczony, filtry, które teraz nazywają się Pipes oraz wiele innych. Wydaje mi się, że pomimo wielu różnic które pojawiły się w nowej wersji (wiele z nich moim zdaniem dobrych), kilka konceptów znanych z pierwszego wydania tego frameworka można zastosować w nowych aplikacjach, które będą już korzystały z najnowszej edycji. Dzięki temu próg wejścia w tą technologię jest dla weteranów AngularJS znacznie mniejszy.

Na dzisiaj to tyle. Tematy, które nie zostały tutaj poruszone na pewno pojawią się w przyszłości. Postaram się także rozwinąć bardziej szczegółowo to, o czym już mówiłem. Zapraszam do komentowania!

Dokładne omówienie założeń gry oraz projektowanie interfejsu aplikacji WordHunt

W zeszłym tygodniu pracowałem trochę nad backend’em aplikacji, a konkretnie zabezpieczaniem API. Chcę zacząć pracować nad interfejsem użytkownika, ale zanim się do tego zabiorę wypada dokładnie przyjrzeć się jak powinien wyglądać. Dlatego dzisiaj opiszę dokładniej jakie jak wyobrażam sobie mechanikę gry i dostępne opcje.

Przebieg rozgrywki

Obecnie zaplanowane mam dwa tryby gry, oba polegające na tym, że wszyscy gracze siedzą razem w pokoju. Rozważam jeszcze dodanie trybu czysto online, ale taki dodam jedynie wtedy, gdy będę miał zapas czasu przed końcem konkursu (czego nie przewiduję…). W grze biorą udział co najmniej dwie drużyny (można ustawić więcej), z czego jedna osoba w drużynie jest kapitanem. Plansza do gry składa się z ustalonej podczas konfiguracji ilości pól (domyślnie 5×5). Na każdym polu zawarte jest jedno słowo. Wszystkie pola są na początku gry zasłonięte, nie wiadomo które pole należy do której drużyny.

Wygląd planszy do gry.

Plansza do gry.

Kapitan ma dostęp do klucza, czyli tak zwanej mapy. Na mapie zawarte są informacje, które pole powinna odkryć (upolować) każda drużyna. Kapitan drużyny wypowiada jedno słowo, które kojarzy się z możliwie największą możliwą liczbą pól jego drużyny oraz mówi, ilu słów dane skojarzenie dotyczy. Jego zawodnicy wybierają następnie na planszy, które pola są wg nich tymi poprawnymi. Jeżeli skończą im się pomysły, mogą zakończyć turę. Ważne jest jeszcze to, że co najmniej jedno pole (także można to konfigurować) jest polem tak zwanej nagłej śmierci, jeżeli któraś z drużyn je odkryje, automatycznie przegrywa. Drużyna wygrywa, gdy jako pierwsza upoluje wszystkie słowa na swoich terenach łowieckich. Gracze mogą korzystać z wbudowanego timer’a, który odlicza pozostały na wykonanie ruchu czas. Można go wyłączyć, traktować tylko jako swego rodzaju upomnienie, że dana drużyna zbyt długo zastanawia się nad ruchem, lub spowodować, że drużyna straci ruch po przekroczeniu dostępnego czasu.

Proponowany wygląd mapy z której korzystają kapitanowie.

Wygląd mapy gry.

Konfiguracje sprzętowe

Pierwszy z trybów przewiduje, że wszyscy gracze będą korzystali z jednego urządzenia (np. tabletu), pełniącego rolę planszy do gry. Wszystkie drużyny będą z niego korzystać do wybierania, które pola wg nich powinni odkryć. Do dyspozycji kapitanów będzie jedno urządzenie (lub więcej, dla wygody każdy może korzystać ze swojego), które będzie wyświetlać mapę gry. Do tego celu idealnie nada się na przykład smartfon. Na innym urządzeniu opcjonalne będzie uruchomienie poglądowej planszy do gry, która nie jest interaktywna np. w salonie na telewizorze. Dzięki temu podczas gdy w zabawie będzie brało udział więcej osób, będą oni dobrze widzieć planszę.

Kofiguracja sprzętowa numer jeden, w której dostępne jest jedno urządzenie interaktywne dla wszystkich, kapitanowie posiadają jedno lub więcej map i dla wszystkich dostępna jest ewentualnie plansza poglądowa.

Przykładowa konfiguracja sprzętowa pierwszego trybu.

Druga konfiguracja różni się tym, że każda z drużyn posiada swoje urządzenie z planszą do gry. Gracze logują się do gry przed jej rozpoczęciem i wybierają którą drużynę reprezentują. Reszta pozostaje bez zmian.

Kofiguracja sprzętowa numer dwa, w której jest każda drużyna ma swoje urządzenie interaktywne, kapitanowie posiadają jedno lub więcej map i dla wszystkich dostępna jest ewentualnie plansza poglądowa.

Przykładowa konfiguracja sprzętowa drugiego trybu.

Cała aplikacja będzie zawierała jeszcze inne ekrany: konfiguracji słownika słów dostępnych w grach, konfiguracji gry czy panel użytkownika. Nie są one jednak kluczowe i nie będę ich dzisiaj przedstawiał. Na koniec zapraszam do komentowania, może podrzucisz mi jakiś ciekawy pomysł, który mogę dodać do rozgrywki. Kolejny raz zachęcam także do odwiedzenia mojego profilu na Twitterze, gdzie postaram się zamieszać więcej aktualizacji dotyczących prac nad projektem!

Zabezpieczenie WebAPI w ASP.NET Core – Wprowadzenie

Dzisiaj chciałbym w skrócie omówić jak zabezpieczyć nasze API, które napisane jest w .NET Core. Jeżeli chcemy mówić o bezpieczeństwie aplikacji, musimy poznać i zrozumieć dwa bardzo ważne pojęcia, które często są ze sobą mylone:

  • Authentication, czyli uwierzytelnianie, to proces podczas którego sprawdzamy, czy dana osoba jest rzeczywiście tym za kogo się podaje.
  • Authorization, czyli autoryzacja, polega na ustaleniu, czy podmiot ma dostęp do zasobu po który wysłał żądanie.

Bardziej na ten temat nie będę się rozpisywał, zachęcam do bardziej dogłębnej lektury, po przeczytaniu mojego wpisu oczywiście.

Zło konieczne

W wielkich systemach zabezpieczenia to sprawa oczywista: finanse, adresy etc. Nikomu nie trzeba tłumaczyć, że te dane pod żadnym pozorem nie mogą wpaść w niepowołane ręce. Jednak rozwijając małą aplikację można sobie pomyśleć: „Po co mi zabezpieczenia, to tylko mały projekt po godzinach, kto chciałby mi się tutaj włamywać?”. Takie myślenie może być zgubne. W sieci grasuje wiele niebezpieczeństw i nawet, jeżeli nie mamy żadnych danych poufnych, to po prostu możemy paść ofiarą zwykłej złośliwości i utracić cenne dla nas dane. Tak mi się skojarzyło z obrazkiem poniżej, za każdym razem jak będziesz odczuwał pokusę udostępniania API bez zabezpieczeń, przypomnij sobie słowa Melisandre.

Satyryczny obrazek postaci z serialu Gra o Tron, ostrzegający o tym że "Internet jest ciemny i pełny strachu"

„Internet jest ciemny i pełny strachu”

Zdając sobie sprawę z zagrożeń o których wspomniałem, przystąpiłem do implementacji mojego API. Osobiście uważam, że jest to bardzo nudna część projektu, zło konieczne z którym trzeba się pogodzić. Cytując słowa Scotta Hanselmana: Shave the Yak, co oznacza mniej więcej tyle, że musimy się uporać z mniejszym problem, żebyśmy mogli przejść do konkretów.

Implementacja JWT Tokens

Na szczęście, do dyspozycji mamy wiele narzędzi które ułatwiają nam życie. Ja moje API zabezpieczam przy użyciu Tokenów JWT. Na razie przedstawię podejście minimalistyczne, w którym będziemy korzystali z indywidualnych kont użytkowników. W przyszłości chcę wykorzystać Social Login, czyli po prostu stare dobre Zaloguj się poprzez fejsbuka, gdzie oczywiście zamiast tego można wykorzystywać także Google, Twittera czy innego GitHub’a. No ale przejdźmy już do konkretów.

Na wstępie musimy dodać bazę danych, gdzie przechowywać będziemy użytkowników. Ja wykorzystam do tego Entity Framework. Dane konfiguracyjne przechowuje w plikach, które nie są wrzucone do repozytorium na GitHubie, a do ich odczytu dodałem własną klasę.

Teraz definiujemy z jakich narzędzi będziemy korzystać. Dzieje się to w pliku Startup.cs, w metodzie ConfigureServices. Najpierw konfigurujemy wykorzystanie systemu identyfikacji Identity dostępnego w paczce Microsoft.AspNetCore.Identity. W tym samym miejscu definiujemy, że do tego cely wykorzystamy właśnie Entity Framework.

Następnie konfigurujemy to, w jaki sposób aplikacja będzie uwierzytelniała użytkowników. Oto fragment tej metody:

UseJwtBearerTokenAuthentication to extension method, który dodałem w celu odchudzenia pliku Startup.cs. To dopiero początek pracy nad projektem, a ten już rośnie w niebezpiecznym tempie. Dlatego staram się wydzielać część konfiguracji do innych plików. Implementacja wspomnianej metody:

Tutaj wprowadzamy nasz tajny klucz, który służy do szyfrowania naszego tokena. Jak poprzednio, przechowuje go w pliku konfiguracyjnym. Definiujemy także to kto wystawia, oraz kto będzie konsumentem naszego tokena. Wszystko to w celu jak najlepszego zabezpieczenia naszej aplikacji.

Ostatnim etapem zabezpieczenia naszej aplikacji jest dodanie klasy, która będzie generowała nam nasze tokeny. Nie będę w całości kopiował tego kodu (kod dostępny w serwisie GitHub tutaj), a tylko kilka kluczowych elementów.

W sytuacji, gdy potwierdzimy tożsamość użytkownika, generujemy klucz, tak samo jak robiliśmy to podczas konfiguracji. Następnie przy pomocy algorytmu HmacSha256 będziemy szyfrować dane. Token zawiera podstawowe informacje o użytkowniku, a także zbiór jego uprawnień, Claims. Dokładniej o tym co zawiera taki token napiszę w innym poście, gdzie opowiem więcej o wspomnianych Claims.

Teraz wywołujemy tą klasę w kontrolerze i nasi użytkownicy mogą wysłać request o token.

Podsumowanie

Gdy przejdziemy przez kroki o których wspomniałem, otrzymamy gotowe rozwiązanie które pozwoli nam w pełni zabezpieczyć naszą aplikację. Nie wspomniałem tutaj o takich pojęciach jak np. CORS oraz SSL, ale myślę że będzie jeszcze ku temu okazja w kolejnych postach. Tymczasem zapraszam do komentowania oraz odwiedzenia mojego Twittera.

Przygotowanie API – REST, czy nie do końca?

Pracę nad moim projektem zacząłem od zadania sobie pytania: jak powinna wyglądać architektura mojego programu? I chociaż na temat samej architektury dodam oddzielny post, potrzebne będzie krótkie wprowadzenie. Głównym założeniem jest powstanie aplikacji dostępnej z poziomu przeglądarki, dzięki czemu będzie można uruchomić ją na komputerach PC oraz Mac, tabletach, a nawet smartfonach. Wiadomo jednak, że na urządzeniach przenośnych dużo wygodniej korzysta się z aplikacji natywnych. Tak powstał kolejny cel, czyli apka na urządzenia zaopatrzone w system Android. Nie postanowiłem jeszcze jak będzie ona wyglądać, ale skłaniam się ku rozwiązaniu w którym będzie ona miała ten sam kod (w miarę możliwości) co strona www, dzięki zastosowaniu rozwiązań takich jak np. Adobe PhoneGap. Jeżeli tak się sprawy mają, to naturalnym wnioskiem dla mnie jest to, że muszę przygotować jakieś API, które mój klient będzie mógł wykorzystać. Tutaj pojawia się kolejne pytanie, na które chcę dzisiaj odpowiedzieć: czy moje API powinno być RESTful, czy też nie? Może wystarczy podejście RPC.

REST czy RPC? I co to takiego?

W celu podjęcia decyzji, postaram się w skrócie opisać te dwa podejścia i wskazać czym się różnią. Oba z tych rozwiązań w tym kontekście operować będą na protokole HTTP. Zapytanie przy użyciu tego protokołu składa się z między innymi:

  • Metody (Mehtod) np. GET, HEAD, POST, która decyduje o tym jaką operację wykonamy na zasobie
  • Nagłówków (Header), w których dostępne są dodatkowe informacje o żądaniu np. dane pozwalające na uwierzytelnianie
  • Ciała zapytania (Content body), które przechowuje informacje np. o zasobie który chcemy dodać/edytować

Niektóre z metod są idempotentne (Idempotent) (z założenia, tak powinny być zaimplementowane), to znaczy że nie ważne ile razy je wykonamy w danych warunkach, zawsze zwrócą tej sam wynik (np. GET i PUT). Inną cechą niektórych metod jest to że są bezpieczne (Safe), czyli nie modyfikują one danych i nie posiadają skutków ubocznych np. GET i HEAD (tak jak poprzednio, w ten sposób powinny być implementowane).

REST, czyli Representational State Transfer to architektura pozwalająca na pisanie skalowalnych usług internetowych. Nie będę rozpisywał się na temat definicji pojęcia REST. Opisując w skrócie: udostępniamy zasoby na których możemy wykonywać różne operacje za pomocą protokołu HTTP. Rodzaj operacji zależy od tego, jakiej metody użyjemy podczas zapytania. Przykładowo, poniższe trzy zapytania będą miały różne wyniki:

  • GET www.example.com/api/objects/2
  • DELETE www.example.com/api/objects/2
  • PUT www.example.com/api/objects/2

W przypadku, gdy mówimy o REST, mamy na myśli podejście zorientowane na zasoby. Definiując adres zasobu używamy rzeczowników, a to jaką akcję wykonujemy nie jest wskazywane przez dodanie czasownika, lecz przez wybór metody HTTP.

RPC (Remote procedure call) ma wiele definicji, ale w tym znaczeniu chodzi o podejście, w którym zamiast operować na zasobach, mamy do czynienia z operacjami. Operacje te w swojej nazwie sugerują co będzie efektem ich wykonania. W przypadku implementacji tego podejścia za pomocą protokołu HTTP wykorzystuje się głównie dwie metody: GET oraz POST. Nie ma tutaj jasno sformułowanych zasad, ale zazwyczaj GET służy do pobierania danych lub akcji, które nie zmieniają żadnych danych, natomiast POST służy do pozostałych operacji. Przykładowe wywołanie takich zapytań:

  • GET www.example.com/api/GetAllObjects
  • POST www.example.com/api/CreateObject

Jeżeli wiemy już jak takie zapytania wyglądają i czym się charakteryzują, możemy przystąpić do porównania. Wezmę pod uwagę kilka czynników, które moim zdaniem są ważne podczas wyboru metody implementacji naszego API.

Projektowanie

Na początek weźmy pod uwagę to, w jak łatwy sposób można projektować nasze API. Jeżeli weźmiemy pod uwagę systemy, które już istnieją np. mamy napisaną już bibliotekę i chcemy w jakiś sposób wyprowadzić ją na świat, łatwiej będzie nam użyć podejścia RPC. Dzieje się tak z reguły dla tego, że większość kodu jaki piszemy jest zorientowany na operacje i łatwiej go w ten sposób odwzorować. Łatwiej też będzie rozwijać system, który głównie opiera się o różnego rodzaju procesy, gdzie jeden obiekt ciągle zmienia się wg jakiejś logiki. Wadą tego podejścia może być to, że ponieważ nie nakłada nam ona żadnych ograniczeń, projektant musi sam pilnować tego, żeby API było spójne i składało się w logiczną całość. Z drugiej strony, REST ułatwia projektowanie prostszych systemów gdzie głównym zadaniem są operacje typu CRUD. Nawet, jeżeli projektowanie API RESTowego może być trudniejsze, dzięki założeniom jakie ze sobą niesie łatwiej otrzymać spójne i logiczne zaplecze dla naszej aplikacji. Tutaj pytanie pozostaje bez odpowiedzi moim zdaniem, ponieważ wszystko zależy od kontekstu w jakim będziemy pracować.

Dokumentacja i jak łatwo ją przygotować

W obu przypadkach możemy wykorzystać narzędzia typu Swagger do udokumentowania naszego API, więc żadne podejście nie jest tutaj lepsze. Sama nazwa zasobu/operacji także może nam sporo powiedzieć o tym, co będzie efektem wywołania danego zapytania. GET www.example.com/api/GetAllObjects czy GET www.example.com/api/objects w jasny sposób mówi nam, co dostaniemy w odpowiedzi, więc można tutaj powiedzieć w pewnym stopniu o tym jak API dokumentuje się samo. Z doświadczenia wiadomo jednak, że takie rzeczy nie zdarzają się zbyt często i trzeba posiłkować się dodatkowymi źródłami wiedzy o naszym requescie.

Semantyka i używalność

W RPC nie jesteśmy w stanie przewidzieć tego, jak dana operacja będzie się nazywać. Ta sama operacja może przybierać taki wygląd:

  • GET/POST www.example.com/api/RemoveObject/1
  • GET/POST www.example.com/api/DeleteObject/1

Zdajemy się tutaj na to, jaki styl wybiera osoba odpowiedzialna za przygotowanie API. Można założyć, że będzie się ona trzymała swojego standardu i podczas usuwania innego rodzaju obiektu użyje tej samej nazwy zapytania. Jednak może się zdarzyć, że za każdym razem trzeba będzie zagłębiać się w dokumentację. REST jest bardziej przewidywalny, dzięki wykorzystywaniu metod HTTP. Nawet, jeżeli nie wiemy dokładnie co stanie się po wykonaniu danej metody, mamy ogólne pojęcie co może być efektem końcowym. W tym przypadku, mój głos dostaje podejście REST, chociaż nie musi zawsze tak być.

Obsługa Cache

Obsługa Cache to jedna z bardzo ważnych rzeczy, które powinna zapewniać nasza RESTowa architektura. Patrząc na specyfikację metod HTTP w łatwy sposób dodać taką obsługę do naszego API. W podejściu RPC jest to dużo trudniejsze, zwłaszcza, gdy zbyt często będziemy korzystać z metody POST. Nie jest to jednak niemożliwe. W tym punkcie można skłaniać się minimalnie w stronę architektury REST.

Podsumowanie

Niektórzy stwierdzą, że wybór naszego podejścia można sprowadzić tylko do osobistych odczuć na temat tego, czy wolimy taki czy inny styl zapytań. Jednak od naszego podejścia w dużej mierze zależy to, w jaki sposób będziemy później pisać nasze aplikacje. Moim zdaniem, głównym czynnikiem jakim powinniśmy się kierować jest to, jaki jest nasz projekt i nie ma sensu od razu zakładać że zrobimy to tak, czy inaczej. Pomimo kilku punktów, w których REST jest lepszym podejściem, np. to że jest bardzo przejrzysty i przewidywalny, ma on też kilka sporych wad i nieudogodnień, które wynikają z jego ograniczeń. Dlatego ja zwykle stawiam na pragmatyzm w moich rozwiązaniach i czerpię to, co najlepsze z danych rozwiązań. Nawet, jeżeli moje API będzie bardziej skłaniało się ku architekturze REST, to nie będę bał się użyć podejścia bardziej skierowanego na operacje. Moim zdaniem POST www.example.com/api/game/1/endturn będzie lepiej opisywało sytuację, niż zmiana właściwości obiektu i wykonywanie konkretnej operacji później.

A jakie jest Twoje zdanie na ten temat? Wszelkie uwagi mile widziane! Zapraszam do komentowania i kolejny raz polecam się na Twitterze!

Relacja z WROC# 2017

Dziś chciałem podzielić się moimi wrażeniami z konferencji WROC# która odbyła się w 3 marca w piątek. Była to już trzecia edycja tego wydarzenia. Po raz pierwszy usłyszałem o niej w zeszłym roku. Słyszałem wtedy, że ciężko zdobyć na nią wejściówkę, ponieważ jest aż tylu chętnych. To, co stało się w trakcie rejestracji przeszło moje najśmielsze oczekiwania. Strona nie zdążyła mi się odświeżyć, a biletów już nie było. Ale to było rok temu. Nie zraziłem się tym i liczyłem że w tym roku będzie lepiej. Miałem ku temu podstawy, ponieważ w tym roku po raz pierwszy wprowadzono opłatę za uczestnictwo w wysokości 150zł. Warto tutaj dodać, że cała kwota zebrana z biletów przekazywana jest na cele charytatywne, tak więc dla organizatora wielki plus. W tym roku mi się udało (inaczej nie pisałbym tej relacji…), ale podobno bilety rozeszły się w około dwie minuty. Jak widać, popularności od zeszłego roku konferencja za dużo nie straciła. No ale przejdźmy już do konkretów!

Przebieg wydarzenia

Po około dwugodzinnej podróży z Zabrza, gdzie mieliśmy zbiórkę przed wyjazdem, przyjechaliśmy pod Stadion we Wrocławiu, gdzie impreza miała miejsce. Rejestracja na takich wydarzeniach może różnie wyglądać, ale tutaj wszystko przebiegało bardzo sprawnie. Dostaliśmy nasze identyfikatory wraz z upominkami, a następnie udaliśmy się na salę gdzie miały odbywać się prelekcje.

Logo WROC#

Dla uczestników dostępny był poczęstunek, drożdżówki, a później różne przekąski w takcie dnia a także obiad w połowie dnia. Wszystko było bardzo smaczne i umilało przerwy pomiędzy wystąpieniami. Dla uczestników dostępne były chillout area oraz working room, gdzie było trochę spokojniej niż w innych rejonach obiektu. Chętni mogli troszkę odsapnąć, lub w razie konieczności popracować. Później każdy chętny mógł podejść do strefy VR, gdzie zobaczyć było można Hololens, Oculus Rift i Touch, HTC Vive czy też PlayStation VR. Organizatorzy przygotowali także dwie gry z nagrodami. Moje ósme miejsce w grze E-maze-ng oraz fakt, że kilka osób nie dotrwało do rozdania nagród, pozwoliło mi wygrać przejażdżkę (tylko jako pasażer, niestety…) samochodem Tesla S P85D! Trzeba przyznać, pomimo niepozornego wyglądu, samochód ten ma niesamowitego kopa!

Prezentacje

Zdjęcie organizatorów witających uczestników konferencji

Openning session

Najważniejsze podczas tego typu wydarzeń, oprócz możliwości porozmawiania z innymi pasjonatami programowania, są oczywiście prelekcje! W kilku słowach postaram się opisać każdą z nich.

Frans Rosén Go hack yourself…or someone else will
Pierwsza prezentacja dnia, gdzie autor opowiadał o tym jak pomaga dbać o bezpieczeństwo witryn sieciowych hackując je i dostając za to nagrody! Można było zobaczyć wiele przykładów na to, czego nie powinno się robić w swoich aplikacjach oraz na co zwracać uwagę. Bardzo mi się podobało, ale jednak nie zacznę szukać dziur w Facebooku albo innych portalach.

Chris Klug AngularJS Tips from the Trenches
W tej prezentacji autor dawał wskazówki na to, jak pisać nasz kod gdy korzystamy z AngularJS. Pomimo, że przykłady dotyczyły tego konkretnego przypadku, wiele z uwag zawartych w tej mowie można wykorzystać podczas pracy z innymi frameworkami np. Aureli. Pomimo, że większość z tego co usłyszałem to podstawy, kilka rzeczy dało mi do myślenia.

Maarten Balliauw What is going on? Tips and tricks around application diagnostics on Azure
Maarten w swojej prezentacji mówił o tym, jak ważne jest zarządzanie naszą aplikacją po tym, jak już zakończymy jej rozwijanie. Czy dobrze działa? Czy użytkownicy wykorzystują jej pełny potencjał? Tego możemy się dowiedzieć jeżeli dobrze podejdziemy do tematu logowania zachowania naszej aplikacji. Spora część prezentacji poświęcona była Application Insights dostępnego na Azure. Drobne problemy z łączem internetowym to nie jest rzadkość podczas takich wystąpień i tym razem nie obyło się bez problemów. Jednak ogół prezentacji i tym razem na plus.

Steve Sanderson ASP.NET Core for Angular 2, React, and Knockout developers
Ta prezentacja troszkę mniej przypadła mi do gustu. Bardzo duża część prezentacji poświęcona szablonom projektów dostępnych dla APS.NET Core dla różnych frameworków. Moim zdaniem trochę za dużo podstaw jak na taką imprezę. Później było troszkę ciekawiej, zwłaszcza możliwość używania możliwości paczek dostępnych z NPM wewnątrz backendu. Ogólnie jednak jedna ze słabszych prezentacji.

Tess Ferrandez Debugging .NET performance problems, memory leaks and crashes
Szczerze przyznam, że podczas tej prezentacji troszkę zbyt mocno pochłonęła mnie gra, którą przygotowali organizatorzy. Jednak było tutaj pokazanych kilka ciekawych sztuczek, które pozwolą nam na optymalizację naszych aplikacji. Na pewno nadrobię to gdy tylko dostępne będą wystąpienia w formie video!

Shawn Wildermuth Developing ASP.NET Core in VS Code
Shawn przybliżał nam możliwości, które daje nam VisualStudio Code. Nie chciał sprzedawać tego środowiska na siłę, wymieniał jego mocne strony, ale także wady. Osobiście nie jestem wielkim fanem tego produktu, dużo bardziej wolę stare dobre VisualStudio. Prezentacja bardzo fajna, ale i tym razem zbyt dużo podstaw jak na taki event.

Po głównych sesjach miejsce miał Discussion panel, gdzie można było zadawać pytania prelegentom za pośrednictwem Twittera. Niestety przegapiłem ten moment, ponieważ musieliśmy odstawić samochód pod hotel. Gdy tylko będzie dostępna relacja z tej części, na pewno zobaczę z przyjemnością.

Afterparty

Po całym dniu technicznych wykładów, organizatorzy przygotowali bardzo wiele atrakcji dla tych, którzy jeszcze nie wracali do domów. Jeszcze więcej pysznego jedzenia, wiele gatunków piwa do wyboru, DJ który rozkręcał parkiet lub kilka stołów z piłkarzykami oraz przejażdżka Teslą dla szczęśliwców, do grona których sam należałem! Była to także świetna okazja do rozmowy z innymi uczestnikami. Było to świetne podsumowanie całej imprezy.

Podsumowanie

WROC# to impreza, której atmosfera oraz organizacja sprawia, że na pewno nie zabraknie mnie tutaj w przyszłości! Liczę jedynie, że będzie troszkę więcej prezentacji związanych z architekturą oprogramowania. Do zobaczenia za rok!

PS. Podczas konferencji pierwszy raz zacząłem bawić się Twitterem. Jeżeli Ty też korzystasz z tej aplikacji, zapraszam do siebie pod adresem @sakwamichal.

Daj się poznać 2017

Słów kilka na powitanie

Cześć, nazywam się Michał i pochodzę z Zabrza. Na co dzień jestem programistą .NET, czym zajmuję się już od blisko 6 lat. Do tej pory siedziałem zwykle po drugiej stronie jako czytelnik, a nie autor tego rodzaju wpisów, ale przyszła i moja kolej żeby się sprawdzić w tej roli. Przyznaję szczerze, że bez motywacji w postaci konkursu Daj się poznać raczej bym się na taki krok nie zdecydował. A jako, że wspomniałem o konkursie, wypada wyjaśnić o co chodzi!

Konkurs „Daj się poznać”

Daj się poznać 2017 to konkurs organizowany przez Maćka Aniserowicza, który prowadzi bloga devstyle.pl. Jest to kolejna edycja tego konkursu, który przyciąga rzeszę programistów, nie tylko związanych ze światem technologi dostarczanych przez firmę Microsoft. W tym roku udało się zebrać ponad 700 uczestników! Z powodu ogromnego zainteresowania rejestracja, która planowo miała trwać do końca lutego, została przedłużona do 12 marca.
Logo konkursu daj się poznać 2017

Ale o co w tym wszystkim chodzi? Sprawa jest bardzo prosta i sprowadza się do dwóch prostych rzeczy: każdy uczestnik musi rozwijać aplikację korzystając z dowolnie wybranych przez siebie technologii oraz dokumentować to wszystko na swoim blogu. To wszystko sprawiło, że jestem tutaj i piszę swój pierwszy wpis. Jestem pewny że będzie to dla mnie nie lada wyzwanie, ponieważ nigdy nie byłem najlepszy w tego typu sprawach. Przejdźmy już do tego, co tygryski lubią najbardziej, czyli samego projektu! Jeżeli interesują Cię szczegóły konkursu, lub sam chcesz wziąć udział, zapraszam na stronę autora konkursu do której link znajduje się powyżej. Masz jeszcze czas!

WordHunt, czyli moja aplikacja konkursowa

To, co w dużej mierze powstrzymało mnie przed wzięciem udziału w konkursie w zeszłym roku, to problem z wyborem odpowiedniego tematu. W tym roku było podobnie, ale po kilku dniach główkowania w końcu udało mi się wpaść na coś, co wydawało mi się w porządku. Inspiracją dla mojej aplikacji była gra towarzyska, w której dwie drużyny próbują odgadnąć które słowa są przydzielone do nich za pomocą skojarzeń, które podsyła kapitan. Plansza składa się z 25 losowych kart i klucza, który znają tylko kapitanowie. Ostatnio pomyślałem sobie, że byłoby fajnie zagrać na większej planszy oraz poszerzyć grę o więcej zespołów. Tak narodził się w mojej głowie pomysł na WordHunt. Pewnie podczas pisania wpadnę na jeszcze więcej pomysłów, ale na razie taki opis powinien wystarczyć. Jeżeli chodzi o technologie których zamierzam użyć, to cały czas rozważam moje możliwości. Na pewno będę starał się wybierać takie, z których nie korzystam w pracy. Przecież o to też tutaj chodzi, o naukę oraz dzielenie się poznaną wiedzą. Z rzeczy na które się już zdecydowałem, backend aplikacji będzie napisany w .NET Core z którym miałem już styczność, ale nie było tego za wiele. Postaram się także użyć nowych dla mnie bibliotek, na przykład Dapper.net. Jeżeli chodzi o interfejs, to tutaj ciągle nie podjąłem decyzji. Vue.js lub Angular2 to mocni kandydaci, ale mam jeszcze trochę czasu żeby to przemyśleć. W planach jest powstanie strony www oraz aplikacji na systemy android, ale zobaczymy ile uda mi się zrobić podczas trwania konkursu.

Głównym celem dla mnie jest dotarcie do końca konkursu. Patrząc na to, ile zajęło mi pisanie tego posta nie będzie to łatwe zadanie, ale zrobię co w mojej mocy żeby tak się stało! Mam nadzieję, że moje przyszłe posty przydadzą się komuś podczas pracy, na pewno sprawiłoby mi to wiele radości. Trzymajcie kciuki i zapraszam ponownie!