Mutagen – synchronizacja plików z Dockerem i nie tylko

W codziennej pracy, programiści pracując na dużej ilości plików chcą mieć do nich bezpośredni i szybki dostęp, a efekt zmian w kodzie powinien być widoczny bez zbędnych i dodatkowych działań. Po drodze spotykamy wiele blokad związanych z konfiguracją, zastosowaną technologią, używanym systemem operacyjnym lub źródłem danych.

Przykłady?

– pracujesz nad dużym projektem PHP w środowisku Dockera na OSX – okazuje się, że montowanie twoich lokalnych plików drastycznie spowalnia działanie aplikacji, a uruchomienie composer install trwa wieczność.

– jesteś zmuszony do wykonania bezpośredniej akcji na plikach znajdujących się na serwerze. Praca przez SSH okazuje się uciążliwa i marzysz o tym, żeby móc pracować na tych plikach lokalnie – w swoim IDE.

– rozpoczynasz pracę nad zdockeryzowaną aplikacją (np. fluentbit, elasticsearch, solr), której konfiguracja zaszyta jest w obrazie. Zamiast tworzyć pliki konfiguracyjne lokalnie i odpowiednio je montować, wolałbyś mieć do nich bezpośredni dostęp „na żywo”.

– pracujesz lokalnie na Ubuntu, a twoja aplikacja uruchomiona jest w Dockerze, z podmontowanymi katalogami. Okazuje się, że aplikacja ma problemy z uprawnieniami do plików i katalogów lub je zmienia, a to tylko początek problemów.

Mutagen

Takie problemy (uproszczone na potrzeby artykułu) można mnożyć bez końca, ale jak sobie z nimi radzić? Z pomocą przychodzi nam jedno narzędzie – Mutagen (https://mutagen.io/).

Mutagen jest narzędziem open-source umożliwiającym proste, wielostronne, w pełni konfigurowalne i błyskawiczne synchronizowanie plików. W porównaniu z podobnymi narzędziami używanymi dotychczas (np. Unison, docker-sync) charakteryzuje się wysoką wydajnością, stabilnością, prostotą użycia, wieloplatformowością oraz aktywnym wsparciem ze strony twórców.

Ogólne działanie sprowadza się do uruchomienia sesji synchronizacji pomiędzy źródłem (alpha) i celem (beta), która na samym początku rozpoznaje użyte środowiska, aby uruchomić na nich proces „agenta„. Agenci komunikują się między sobą za pomocą dobranego protokołu (SCP, Docker API i inne) i obserwują zmiany na plikach. Dalsze działanie, przenoszenie zmian, ignorowanie konkretnych plików, zarządzanie uprawnieniami i symlinkami konfigurowalne jest za pomocą pliku yaml.

Od wersji 0.10 Mutagen wspiera również orkiestrację synchronizacji na poziomie projektu (https://mutagen.io/documentation/orchestration/) oraz kierowanie ruchem sieciowym (https://mutagen.io/documentation/forwarding/).

Poniżej przedstawiam przykładową konfigurację synchronizacji plików dla aplikacji Symfony Demo w systemie OSX z pomocą Mutagena w wersji 0.10.

Zacznijmy od instalacji Mutagena:

 brew install mutagen-io/mutagen/mutagen

Po instalacji należy uruchomić daemon process aplikacji i zarejestrować go w autostarcie systemu:

mutagen daemon start
mutagen daemon register

Mając uruchomioną aplikację Docker, z odpowiednimi kontenerami PHP i Nginx, oczekującymi na pliki w katalogu /var/www/symfony możemy uruchomić nasze sesje synchronizacji.

➜  docker-compose up -d
Creating network "sync-example_default" with the default driver
Creating sync-example_mysql_1 ... done
Creating sync-example_php_1   ... done
Creating sync-example_nginx_1 ... done


➜  docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                               NAMES
f1382f624b00        sync-example_nginx   "nginx"                  15 seconds ago      Up 13 seconds       0.0.0.0:80->80/tcp                  sync-example_nginx_1
a6f42a5c3c89        sync-example_php     "php-fpm7 -F"            16 seconds ago      Up 14 seconds       0.0.0.0:9000->9001/tcp              sync-example_php_1
1a9cec92ed8e        mysql:5.7            "docker-entrypoint.s…"   17 seconds ago      Up 15 seconds       0.0.0.0:3306->3306/tcp, 33060/tcp   sync-example_mysql_1

Tworzymy plik mutagen.yml z przykładową zawartością:

sync:
  defaults:
    ignore:
      paths:
        - .DS_Store
  code:
    alpha: "./symfony"
    beta: "docker://sync-example_php_1/var/www/symfony"
    mode: "one-way-safe"
    ignore:
      vcs: true
      paths:
        - "/build/"
        - "/vendor/"
        - "/var/"
  composerjson:
    alpha: "./symfony/composer.json"
    beta: "docker://sync-example_php_1/var/www/symfony/composer.json"
    mode: "two-way-resolved"
    watch:
      pollingInterval: 2
    permissions:
      defaultFileMode: 666
      defaultDirectoryMode: 777
    ignore:
      vcs: false
    symlink:
      mode: "ignore"
  composerlock:
    alpha: "./symfony/composer.lock"
    beta: "docker://sync-example_php_1/var/www/symfony/composer.lock"
    mode: "two-way-resolved"
    watch:
      pollingInterval: 2
    permissions:
      defaultFileMode: 666
      defaultDirectoryMode: 777
    ignore:
      vcs: false
    symlink:
      mode: "ignore"
  var:
    alpha: "./symfony/var"
    beta: "docker://sync-example_php_1/var/www/symfony/var"
    mode: "two-way-resolved"
    watch:
      pollingInterval: 5
  vendor:
    alpha: "./symfony/vendor"
    beta: "docker://sync-example_php_1/var/www/symfony/vendor"
    mode: "two-way-resolved"
    watch:
      pollingInterval: 5
    ignore:
      vcs: false

Zawartość pliku należy dostosować do swoich nazw kontenerów (format to docker://NAZWA_KONTENERA/SCIEZKA). Poszczególne klucze w pliku wyjaśnione są w dokumentacji pod adresem https://mutagen.io/documentation/. Podczas tworzenia konfiguracji, należy zwrócić uwagę na klucze „mode„, „pollingInterval” oraz na wielkość synchronizowanych katalogów. Każdy z tych elementów ma wpływ na wydajność i obciążenie generowane przez procesy „mutagen agent” w kontenerach i na hoście.

Moje doświadczenia potwierdzają, że nawet bardzo duży projekt może być synchronizowany w całości z minimalny obciążeniem CPU. Warunkiem koniecznym jest dobranie odpowiedniej konfiguracji, nawet kosztem dużej ilości sesji mutagena.

Tworzymy nasz projekt Symfony Demo w katalogu symfony:

composer create-project symfony/symfony-demo symfony

Następnym krokiem będzie uruchomienie stworzonych sesji projektu:

mutagen project create mutagen.yml

W rezultacie otrzymamy listę ID utworzonych sesji. Aby sprawdzić ich status należy wywołać komendę

mutagen list

Aby obserwować zachodzące zmiany oraz status transferowanych plików, możemy użyć komendy:

mutagen monitor {ID_SESJI}

Już po paru sekundach na naszych kontenerach znajduje się cała zawartość projektu. Pliki vendora będą synchronizowane dwustronnie, a pliki projektu jednostronnie (w przypadku ewentualnych konfliktów zostaną one wyświetlone po użyciu mutagen list).

Powyższa konfiguracja jest jedną z bardziej skomplikowanych. Jeżeli interesuje nas synchronizacja tylko jednego katalogu (np. konfiguracji PHP w obrazie) wystarczy, że wywołamy komendę:

mutagen create -m two-way-safe docker://sync-example_php_1/etc/php7 ~/Desktop/php

a na naszym pulpicie pojawi się synchronizowany katalog z kontenera, w praktyce działający tak szybko, jak gdyby był podmontowany.

Sesje możemy oczywiście w dowolnej chwili zatrzymywać i wznawiać, usuwać i tworzyć. Nad wszystkim panuje aplikacja.

Podsumowując, uważam, że dzięki Mutagenowi synchronizacja plików nie jest już smutną koniecznością, a narzędziem, które stwarza nowe możliwości. Możemy na przykład w prosty sposób pozbyć się obciążenia komputera, wynosząc warstwy aplikacji poza lokalne środowisko, działając jedynie na IDE.

Serdecznie polecam to narzędzie oraz zachęcam do wspierania twórcy.

Podczas tworzenia artykułu, korzystałem z poniższych linków:
https://mutagen.io/
https://github.com/mutagen-io/mutagen
https://github.com/symfony/demo
https://github.com/coloso/symfony-docker

Autorem tekstu jest Janusz Maciejewski.

NgRx – stan aplikacji angularowych

NgRx

Zarządzanie stanem aplikacji frontendowej może być trudne, a stopień trudności rośnie wraz rozwojem aplikacji.

Dzisiaj po krótce chciałbym opisać wiodącą bibliotekę pozwalającą na tworzenie i zarządzanie tymże stanem. Będzie mowa o tytułowym NgRx.

Na początek postaram się powiedzieć skąd wzięła się ta biblioteka i jakie problemy rozwiązuje, następnie omówię elementy składowe NgRx, a później przejdę do zalet i wad tego rozwiązania oraz dostępnych alternatyw.

A więc czym jest NgRx?

Zgodnie ze wpisem w dokumentacji:

NgRx jest zbiorem bibliotek do budowania reaktywnych aplikacji z wykorzystaniem Angulara. NgRx udostępnia zarządzanie stanem, izolację efektów ubocznych, zarządzanie kolekcjami encji, jest powiązany z „rouetrem” Angulara, pozwala na generowanie kodu oraz na korzystanie z narzędzi programistycznych usprawniających pracę.

Nie jest to jednak nowy pomysł w świecie frameworków frontendowych. Pracownicy z firmy Google (NgRx podobie jak Angular ma swoje początki właśnie w gigancie z Mountain View, aktualnie jest rozwijany przez społeczność) nigdy nie kryli faktu, iż główną inspiracją był Redux szeroko wykorzystywany w środowisku Reacta. Redux natomiast jest implementacją Fluxa, który został zaprezentowany jako wewnętrzna architektura w innym z amerykańskich gigantów mianowicie w znanym i lubianym Facebooku.

Elementy składowe NgRx

NgRx składa się z kliku bibliotek:

* @ngrx/store
* @ngrx/effects
* @ngrx/router-store
* @ngrx/entity
* @ngrx/schematics

Podstawowe funkcjonalności zawierają się w @ngrx/store i @ngrx/effects, @ngrx/router-store pozwala na integrację z routerem angualra, @ngrx/entity pomaga w operacjach na dużych kolekcjach, zaś @ngrx/schematics zawiera zbiór schematów pozwalających na generowanie kodu za pomocą wiersza poleceń.

Akcje

Akcja to zwykła klasa implementująca interfejs Action z @ngrx/store, posiada typ oraz opcjonalny „payload” przez, który przekazujemy dane. Zazwyczaj są wykorzystywane w komponentach w celu wykonania jakieś operacji (zmiany stanu lub/i wywołania efektu).

Reducery

Reducer jest zwykłą funkcją przyjmującą 2 parametry, aktualny stan aplikacji oraz akcję. Jego zadaniem jest zwrócić nowy stan aplikacji.

Efekty

Do efektów oddelegowane są wszystkie asynchroniczne operacje, w szczególności zapytania do api. Do efektów wstrzykujemy serwisy komunikujące się z zewnętrznymi usługami, po wykonaniu operacji efekt musi zwrócić akcję, która jest przekazywana do reducera w celu zmiany stanu.

Selektory

Selektory odpowiadają za dostarczenie danych ze stanu aplikacji.

Zalety

Największą zaletą biblioteki jest bez wątpienia rozwiązanie problemu zarządzania stanem aplikacji, dzięki temu komponenty tworzące przez programistę mogą być znacznie prostsze, ponieważ znaczna część logiki jest oddelegowana do efektów, reducerów i selektorów.
Ponadto, traktując stan jako „jedyne źródło prawdy” nie musimy przejmować się synchronizacją danych pomiędzy komponentami, które mogą prezentować te same dane w różny sposób. Zastosowanie NgRx’a można z powodzeniem stosować wraz z architekturą „smart/dump componets”, która pozwala na korzystanie z strategii detekcji zmian „OnPush”. Oprócz tego dostępne jest narzędzie dla programistów pozwalające na łatwe odnajdywanie błędów.

Wady

Do wad bez wątpienia możemy zaliczyć ilość kodu, która początkowo może wydawać się przytłaczająca. Mamy do dyspozycji narzędzie do generowania wszyskich elementów składowych, lecz na początku przygody z NgRx niewiele to daje. Bez wątpienia nie jest to najłatwiejsza biblioteka do opanowania. Wymaga również znajomości innej z bibliotek, na której jest oparta, mianowicie rxjs.

Alternatywy

Do dyspozycji mamy np. NGXS, które jest nieco prostszą i okrojoną wersją NrRx’a oraz bibliotekę Aita, która może być wykorzystywana nie tylko w frameworku Angular, lecz również w innych wiodących frameworkach js.

Autorem tekstu jest Łukasz Zięba.

GraphQL – Pobieraj tylko to, co chcesz!

Czy zdarzyło Wam się kiedyś, że zwracaliście w API dane, które nie zawsze były wykorzystywane, a jedynie przydawały się w konkretnych sytuacjach? Na przykład: potrzebowaliście listy przedmiotów tylko po nazwie, a API zwraca dodatkowo kategorię oraz powiązane przedmioty, które nie są potrzebne w danej sytuacji, jednak inne miejsca w systemie z nich korzystają (over-fetching)? Albo wręcz odwrotnie – mieliście zbyt mało danych? Przez co, celem wyświetlenia listy produktów, musieliście wykonywać kolejne requesty, by pobrać informacje o powiązanych produktach (under-fetching)?

Możemy w takiej sytuacji tworzyć dedykowane endpointy lub też parametryzować (w zależności od interesujących nas informacji), ale zarządzanie takim API może stawać się z czasem coraz bardziej uciążliwe i nieefektywne.

GraphQL

Na szczęście z pomocą przychodzi nam opracowany przez firmę Facebook silnie typowany język zapytań GraphQL. Intuicyjna składnia GraphQL pozwala na pobieranie danych (Query), ich edycję i wstawianie (Mutation) oraz obserwowanie zmian w czasie rzeczywistym (Subscription). Język ten pozwala dokładnie określić jakie dane nas interesują na wyjściu, jak głęboko chcemy pobierać obiekty powiązane ze sobą oraz co dokładnie chcemy modyfikować.

Przykłady

Tworzymy typ “Product”, który posiada nazwę, powiązane produkty oraz kategorię. Jest on wykorzystany w domyślnym typie “Query” – wymaganym do działania. Tak stworzony schemat pozwala nam na pobranie wszystkich produktów i produktów powiązanych, wraz z kategoriami.

type Query {
  allProducts: [Product]!
}

type Product {
  id: ID
  name: String
  related: [Product]!
  categories: [Category]!
}

type Category {
  id: ID
  name: String
}

Spróbujmy pobrać listę produktów (id, name), kategorie (name), oraz powiązane przedmioty (id, name) wraz z przypisanymi im kategoriami (name).

{
  allProducts {
    id
    name
    categories {
	name
    }
    related {
      id
      name
      categories {
	  name
      }
    }
  }
}

Jeśli potrzebowalibyśmy dodatkowych zagnieżdżeń, możemy je po prostu dopisać:

[...]
    related {
      id
      name
      categories {
	  name
      }
      related {
        id
        name
        categories {
	    name
        }
      }
    }
[...]

Wysyłając nasze pierwsze query do serwera, możemy otrzymać przykładowe dane:

{
  "allProducts": [
    {
      "id": 153,
      "name": "kolczyki",
      "categories": [
        {
          "name": "Biżuteria"
        }
      ],
      "related": [
        {
          "id": 156,
          "name": "pierścionek złoty",
          "categories": [
            {
              "name": "Biżuteria"
            },
            {
              "name": "Złoto"
            }
          ]
        }
      ]
    },

  [...]
  ]
}

Jak widać, otrzymaliśmy dokładnie to, o co prosiliśmy.

Przedstawiony został tu uproszczony przykład tylko dla operacji Query, więcej przykładów można znaleźć na oficjalnej stronie https://graphql.org/learn/.

Autorem tekstu jest Maksym Kuras.

API Platform

Kilka słów o API Platform

Obecnie wymiana danych między zewnętrznymi systemami jest niezbędnym elementem wszelkich aplikacji. Świetnie sprawdzi się w platformach nastawionych na sprzedaż wielokanałową, gdzie dane pochodzą z różnych źródeł. Mowa o omnichannel ecommerce. Udostępnianie danych oraz możliwość ich modyfikacji jest możliwa między innymi dzięki API, czyli ​pewnemu ściśle określonemu zestawowi reguł i ich opisów, w jaki programy komputerowe komunikują się między sobą​. Jest to chyba najbardziej znany, bezpieczny oraz optymalny sposób. Jest to przeważnie API oparte o styl architektoniczny REST.

Takie API musi być przede wszystkim zrozumiałe i czytelne dla wszystkich, którzy będą z niego korzystali. Interfejs API powinien mieć dobrą dokumentację, najlepiej z przykładami. W celu stworzenia API wraz z wartościową dokumentacją można skorzystać np. z API Platform.

API Platform

API Platform zostało utworzone w roku 2015 przez Kevina Dunglasa. Zawiera bibliotekę PHP. Jest to narzędzie oparte na frameworku PHP Symfony.

Jak szybko stworzyć API?

Poniżej przykład jak stworzyć API z użyciem API Platform dla prostego modelu CRUD.

1. Projekt tworzymy poprzez polecenie

composer​​ create-project symfony/skeleton nazwa-projektu

Utworzy nam to folder z nazwą projektu oraz zainstaluje pierwsze niezbędne paczki. symfony/skeleton t​o minimalna opcja projektu, która instaluje tylko zależności niezbędne do działania Symfony.

2. Następnie odpalamy polecenie:

composer​​ require api

które instaluje nam właśnie API Platform.

3. Teraz dla przykładu możemy sobie w katalogu Entity utworzyć prosty model, np. User.php.

<?php namespace App\Entity; use ApiPlatform\Core\Annotation\ApiResource; /** * @ApiResource */ class User { /** @var string */ private $id; /** @var string */ private $firstName; /** @var string */ private $lastName; /** @var string */ private $email; public function __construct( string $id, string $firstName, string $lastName, string $email ) { $this->id = $id;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->email = $email;
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function getFirstName(): string
    {
        return $this->firstName;
    }

    public function getLastName(): string
    {
        return $this->lastName;
    }

    public function getEmail(): string
    {
        return $this->email;
    }
}

4. Pod adresem http://127.0.0.1:8000/api mamy już gotową dokumentację API wraz z możliwością wysyłania requestów.

Zalety

– szybkość
– nie powtarzanie tego samego kodu w wielu miejscach
– jasna i przejrzysta dokumentacja z możliwością requestów

Jest to tylko bardzo krótki opis, gdyż API Platform posiada o wiele więcej możliwości. Są to między innymi:

– tworzenie, pobieranie, aktualizowanie i usuwanie zasobów (CRUD)
– walidacja danych
– stronicowanie
– filtrowanie
– hypermedia (JSON-LD, HAL)
– GraphQL
– Nagłówki CORS
– wsparcie dla JWT

Źródła: ​https://api-platform.com/docs

Autorem tekstu jest Piotr Smaruj.

Free Plan

O czym jest ten artykuł?

Serverless zdobywa świat! Czy Serverless to dobra nazwa? Cóż, tak to ktoś wymyślił, tak się przyjęło, nikt tego już nie zmieni. Oczywiście, małą niekonsekwencją może wydawać się obecność serwerów pod maską technologii Serverless, ale, w sumie, można powiedzieć, wszystko jest kwestią perspektywy. Co jednak ważne – technologia ta daje nam, programistom, dość ciekawe możliwości, z których, między innymi, postaram się skorzystać w tym artykule.

Od razu przyznam się też do inspiracji, w tym przypadku był nią jeden z odcinków vloga „fun fun function” – kilka pomysłów z tego odcinka wykorzystałem w moich własnych eksperymentach.

Cel – najlepiej opisać go chyba jako „wycieczkę” po narzędziach i technologiach, które, albo są już dzisiaj standardem, albo po prostu, mnie osobiście, wydają się interesujące. Wszystkie narzędzia/serwisy będą wykorzystywane tylko w wersji darmowej – stąd tytułowy „free plan” – czyli bez kosztów dla nas – deweloperów, co oczywiście jest super w zastosowaniach hobbystycznych i jednocześnie (przeważnie) zupełnie nie nadaje się do zastosowań biznesowych (z czego wszyscy, mam nadzieję, zdajemy sobie świetnie sprawę).

Jako tło dla niniejszego artykułu wykorzystałem prostą aplikację Gls (mojego autorstwa), której główną funkcjonalnością jest animowanie obiektów Gls (wiem, na razie to pewnie niewiele mówi). Aplikacja posłuży mi tutaj głównie jako przykład praktycznego wykorzystania poszczególnych narzędzi.

Zapraszam do lektury!

Narzędzia

Programiści, jak wszyscy rzemieślnicy (Software craftsman) potrzebują dobrych narzędzi!

Pisząc ten artykuł wykorzystałem: GitHub, Docker Hub, Node.js, Npm, Webpack, Unpkg, OpenShift, Observable, Firebase, Heroku i Miro. Dodatkowo chciałem, ale musiałem zrezygnować ze względu na uciekający czas, skorzystać również z CircleCI, Travisa, Zeit i wypróbować CloudFlare – może następnym razem się uda.

Niestety, nie starczy tutaj miejsca na dokładniejszy opis wszystkich tych technologii, w paragrafie „Repetytorium” (nazwa trochę przewrotna) umieszczam krótką informację odnośnie tych z powyższych narzędzi, z których dokładniejszego opisu tutaj zrezygnowałem. Oczywiście, dla lektury samego artykułu, znajomość wszystkich tych technologii nie jest istotna – cel to w końcu, również, ich prezentacja (choć niekiedy bardzo krótka) czytelnikowi.

Diagram – spojrzenie na aplikację

Nic tak nie ułatwia zapoznania się z jakimś większym planem, jak spojrzenie na diagram przedstawiający jego najistotniejsze elementy. Miro jest jednym z narzędzi, które pozwalają tworzyć diagramy, czy „wirtualne tablice”, do wykorzystania w pracy zespołowej. Aby przetestować ten serwis (choć w zespole jednoosobowym) postanowiłem stworzyć, za jego pomocą, trochę schematów odnośnie aplikacji Gls (o której więcej za chwilę). Schematy te są dostępne pod adresem https://miro.com/app/board/o9J_kxlNBbU=/ (oczywiście stworzone są w ramach konta „free”). Umieściłem tam również Kanban Board realizacji Gls – jak widać, niestety nie wszystko udało się zakończyć.

Jeżeli ktoś zna/pracował z Enterprise Architect to muszę zaznaczyć, iż Miro, moim zdaniem, nie stanowi jego odpowiednika, a raczej uzupełnienie (ciekawą możliwością byłaby migracja schematów pomiędzy tymi dwoma narzędziami). To, czego brakuje mi w Miro na dzień dzisiejszy, to z pewnością możliwość tworzenia diagramów UML – Miro to bardziej narzędzie ogólnego przeznaczenia, z naciskiem na biznesowe prezentacje, niż narzędzie dedykowane programistom. Ale chyba warto obserwować ten projekt.

Aplikacja

Aplikacja Gls składa się z poniższych elementów – wszystkie zostaną omówione/wykorzystane:

• Silnik “przeliczający” obiekty Gls – biblioteka Gls
• Prezentacja obiektów Gls – aplikacja Gls-Web
• Wsparcie przy edycji obiektów Gls – Observable, tylko edycja, edycja + zapis do bazy
• Client API dostępu do bazy danych – Gls-Db-Api-Client
• API bazy danych – Gls-Db-Api
• Baza danych

Wszystkie te elementy zostały zaznaczone na poniższym schemacie:

Pod tym linkiem znajduje się  „interaktywna” wersja powyższego diagramu z linkami prowadzącymi do odpowiednich „elementów” aplikacji,
link ukryty pod nazwą “Gls-Web Hosting” powinien prowadzić do wersji aplikacji hostowanej na platformie OpenShift. Tutaj małe wyznanie – korzystanie z “free plan” ma oczywiście wady o których należy pamiętać – jedną z nich jest z pewnością duża „dynamika” dostępności elementów aplikacji. Oznacza to ni mniej, ni więcej, tylko tyle, że adresy url do elementów hostowanych na platformach Serverless (przynajmniej w przypadku aplikacji Gls) mają dużą tendencję do zmian – dlatego unikam w tym artykule wklejania bezpośrednich linków do aplikacji/“endpointów”, ponieważ artykuł raczej nie będzie edytowany – zamiast tego będę się starał utrzymywać w miarę aktualne linki na schemacie dostępnym poprzez Miro.

Kto odważny – niech kliknie w link z chmurki „Gls-Web Hosting”!

Funkcjonalność aplikacji nie jest tutaj najważniejsza (to nie jest artykuł o aplikacji Gls!), nie jest też celem udowodnienie słuszności zastosowanej architektury – najpewniej inni programiści rozwiązali by pewne kwestie inaczej – to tylko przykład!

Uwaga co do nazewnictwa: nazwy Gls używam w kilku kontekstach:

• Gls jako cała aplikacja – cały projekt
• Gls jako obiekt json – czyli dane do wyświetlenia / renderowania
• Gls jako biblioteka https://github.com/lbacik/gls

Zachowajcie czujność!

Repetytorium

Tak jak zaznaczałem w paragrafie „Narzędzia”, poniżej zamieszczam „kilka słów” o niektórych z wykorzystanych technologii:

Git & GitHub

Stworzony w pierwszej dekadzie tego wieku przez Linusa Torvaldsa Git, to jeden z aktualnie najpopularniejszych rozproszonych systemów kontroli wersji. GitHub natomiast to… chyba można ten serwis nazwać jednym ze współczesnych „bazarów” (nawiązując do eseju Erica Raymonda „Katedra i Bazar” – ciekawym może wydawać się fakt, iż obecnie właścicielem serwisu GitHub jest firma Microsoft). W tym miejscu, zamiast linków do dokumentacji (myślę, że w razie potrzeby znalezienie w Internecie informacji o tych narzędziach nie będzie żadnym problemem), chciałbym polecić (tym którzy jeszcze nie oglądali) prezentację Linusa, dotyczącą Git-a, wygłoszoną w siedzibie Google 12 lat temu: https://www.youtube.com/watch?v=4XpnKHJAok8.

Kontenery, Docker & Docker Hub

Docker nie jest jedynym, aktualnie dostępnym, wysokopoziomowym narzędziem do zarządzania Linuksowymi Przestrzeniami Nazw (Linux Namespaces) – ale chyba przyjął się najlepiej! W końcu ilu deweloperów zna Lxc/Lxd czy Rkt? Ponieważ wszystkie te narzędzia są mimo wszystko dość podobne (wszystkie wykorzystują ten sam mechanizm, którym są Linuksowe Przestrzenie Nazw (Linux Namespaces), to trochę może dziwić tak duża dysproporcja w ich rozpoznawalności wśród programistów (i nie tylko). Co więc stoi za tak dużym sukcesem Dockera? Każdy może mieć oczywiście swoją teorię, ja stawiałbym na serwis Docker Hub – moim zdaniem, globalne repozytorium „dockerowych” obrazów (docker images), to był przysłowiowy strzał w dziesiątkę!

Do aplikacji Gls-Web dodany został plik Dockerfile. To pozwala zbudować każdemu kontener lokalnie. Taki „obraz”, w przypadku własnych projektów, można wysłać do repozytorium Docker Hub, aby udostępnić go innym użytkownikom. Jednak, jeżeli eksport nie jest jednorazowy i chcemy utrzymywać synchronizację pomiędzy projektem w serwisie GitHub a obrazem w serwisie Docker Hub to lepszym rozwiązaniem będą aktualizacje automatyczne. W tym celu, dla projektu na Docker Hub, możemy wybrać integrację z GitHub (do wyboru jeszcze Bitbucket), a następnie ustawić „wyzwalacz” (trigger) na wskazany branch w repozytorium Git. Oznacza to, że po wprowadzeniu zmian do tego, wybranego brancha, Docker Hub automatycznie rozpocznie budowanie kontenera wg pliku Dockerfile w repozytorium. Tak skonfigurowałem to właśnie w przypadku Gls-Web i Gls-Db-Api – obrazy Gls-Web i Gls-Db-Api są budowane automatycznie po każdej zmianie w projektach (branch master) Gls-Web i Gls-Db-Api!

Więcej informacji w dokumentacji na docker.com, oraz w pliku README.md projektu Gls-Web.

Node.js, Npm, Webpack & Unpkg

Aplikacja Gls została napisana w JavaScript, z wykorzystaniem Node.js.

Node.js to „środowisko uruchomieniowe” dla języka JavaScript, które powstało z myślą o wykorzystaniu JS w tzw. backendzie. Termin „środowisko” okazuje się mieć tutaj znaczenie, co w świetny sposób tłumaczy Philip Roberts w prezentacji: What the heck is the event loop anyway?, opisującej sposób działania JS w przeglądarce jak i w implementacji Node.js.

Npm to manager pakietów dla Node.js – jednak, nie tylko. Pozwala on również na publikowanie własnych bibliotek w centralnym repozytorium (tak, aby inni programiści mogli je pobrać i wykorzystać w swoich projektach).

Aby umożliwić korzystanie z biblioteki Gls (i Gls-Db-Api-Client) w środowisku JS przeglądarki skorzystałem natomiast z Webpack i Unpkg – poniżej wyjaśnię ich rolę, to w sumie ciekawa kwestia świata JS.

Gls-Web wykorzystuje bibliotekę Gls w dość specyficzny sposób. Gdy kod biblioteki Gls na zostać dołączony do dokumentu HTML wysyłanego do przeglądarki, “backend” korzysta z metody code, klasy Generator, której rezultatem jest zwrócenie (w postaci ciągu znaków) całego kodu biblioteki Gls potrzebnego do renderowania obiektów Gls w przeglądarce (kod ten możemy znaleźć w źródle dokumentu HTML).

1. To dość toporna metoda.
2. Z metody takiej nie możemy skorzystać w aplikacjach typu Observable (o Observable napiszę w jednym z kolejnych paragrafów) ponieważ nie mamy dostępu do kodu działającego w backendzie.

Punkt pierwszy możemy rozwiązać/poprawić przygotowując wersję naszej biblioteki w formacie UMD. Aby rozwiązać problem z pkt 2 możemy udostępnić przygotowaną wersję UMD poprzez serwis typu Unpkg.

Weźmy bibliotekę Gls – jeżeli chcielibyśmy „wczytać” ją z poziomu przeglądarki, wykorzystując np. link https://unpkg.com/@lbacik/gls (Unpkg zaserwuje nam w takim przypadku plik wskazany w package.json jako „main” – czyli naszą fabrykę to tworzenia obiektów Gls), to niestety to nie zadziała – runtime JS uruchomiony w przeglądarce nie będzie wiedział jak interpretować polecenia „require” – czyli jak dołączyć pozostałe pliki pakietu…

Tutaj na scenę wchodzi UMD – specyfikacja ta pozwoli nam przygotować odpowidnią wersję biblioteki Gls. Oczywiście nie chodzi o przepisanie biblioteki od zera, a wykorzystanie jednego z narzędzi, które skonwertuje naszą bibliotekę (przygotowaną dla Node.js) do odpowiedniego formatu (umożliwiającego jej wykorzystanie w środowisku przeglądarki) – ja zdecydowałem się na wykorzystanie do tego celu właśnie narzędzia Webpack. W katalogu głównym biblioteki Gls umieściłem plik konfiguracyjny webpack.config.js, oraz przygotowałem „skrót” do wywołania webpacka w `package.json`, sama biblioteka natomiast wskazana jest w zależnościach środowiska developerskiego aplikacji.

Wywołując przygotowany skrót:

$ npm run build

generowana jest wersja pakietu w formacie UMD. Ta wersja zostaje zapisana w katalogu `dist`. Sam katalog `dist` wyłączony jest z zapisu w repozytorium git (plik .gitignore), ale włączony jest do uploadu do repozytorium npmjs.com (plik package.json, klucz „files”). Czyli, po opublikowaniu pakietu na npmjs.com, wersja pakietu Gls przygotowana przez narzędzie Webpack będzie dostępna, poprzez serwis Unpkg, pod adresem url: https://unpkg.com/@lbacik/gls/dist/gls.js

I to jest to! Skorzystamy z tej wersji pakietu Gls (jak i również analogicznie przygotowanej wersji pakietu Gls-Db-Api-Client) w aplikacji Observable. Oczywiście w profesjonalnych aplikacjach takie „dystrybucyjne” wersje powinny być jeszcze minimalizowane, aby ograniczyć ich rozmiar, ale ja już odpuściłem ten krok (przynajmniej w aktualnej wersji aplikacji Gls).

Serverless – starcie pierwsze

Czas na pierwsze starcie z Serverless! Docker Hub to bardzo przydatne narzędzie – jednak, dany kontener, musimy pobrać i uruchomić lokalnie (bądź też, mówiąc bardziej ogólnie – w ramach swojej infrastruktury). To nie sprawi problemu osobom zaznajomionym z tą technologią, jednak większość potencjalnych użytkowników wolałaby chyba po prostu dostać adres url, który mogliby „kliknąć” i cieszyć się aplikacją. Czy udostępnienie takiego, globalnego adresu url, bez opłacenia dostępu do jakiejś platformy hostingowej, serwera VPS czy tego typu rzeczy, jest możliwe? Okazuje się, że aktualnie, w tej kwestii „nie jest źle”, a z pewnością, w przyszłości, będzie coraz lepiej!

W pierwszym starciu sięgnąłem po sprawdzone (w moim przypadku) już rozwiązanie – openshift.com.

OpenShift to platforma rozwijana przez Red Hat i zbudowana z wykorzystaniem technologi od Google (przynajmniej pierwotnie) – Kubernetes. W planie „free”, mamy do dyspozycji 4 pody (każdy z 0.5 GB Ram) – to naprawdę nieźle! W trakcie konfiguracji projektu możemy wskazać dockerowy image dostępny np. w serwisie Docker Hub, image ten zostanie pobrany i uruchomiony w jednym z podów, domyślnie, bez możliwości dostania się do aplikacji z Internetu, ale jednym/dwoma kliknięciami, bez problemu, zdefiniujemy odpowiedni routing. Po aktualny adres aplikacji Gls-Web hostowanej na OpenShift odsyłam do schematu na Miro – chodzi mi tutaj o link opisany na diagramie jako „Gls-Web Hosting” – adres, który ukrywa się pod tym linkiem, będzie raczej trudny do zapamiętania, ale na testy/demo w zupełności wystarczy.

Tak więc, użytkownik nie musi pobierać kodów źródłowych z GitHub (i budować aplikacji lokalnie), czy kontenera z Docker Hub – możemy przygotować również opcję z dostępem po url!

Observable

Gls-Web pozwala przeglądać przygotowane wcześniej obiekty Gls. Brakuje jednak jakiegoś „edytora” tych obiektów – narzędzia, które można by wykorzystać przy ich tworzeniu.

Obiekty Gls to obiekty typu json, kilka przykładów można znaleźć w katalogu examples projektu Gls-Web (przykłady z tego katalogu są wyświetlane w podstawowym trybie pracy aplikacji Gls-Web, są to przykłady z zakładki „local” – bądź też jedyne widoczne przykłady, jeżeli url do bazy danych nie został przekazany do Gls-Web).

Oczywiście, można rozbudować aplikację Gls-Web o jakiś prosty edytor plików Gls, ale… zróbmy użytek z naszej dekompozycji i spróbujmy poeksperymentować z Observable!

Ogólnie Observable można chyba nazwać narzędziem do zabaw z JavaScriptem. Dostarcza ono nam dość szczególnego środowiska pracy dla naszych skryptów – pozwalającego na przygotowanie interakcji w (jak dla mnie) dość nowatorki sposób. Dysponujemy notatnikiem w którym możemy osadzać skrypty i elementy HTML – skrypty oczywiście mogą wymieniać między sobą dane, kontrolować różne osadzone elementy, takie jak suwaki, czy renderować grafikę. Wszystkie zmiany w notatniku są śledzone, mamy możliwość „forkowania” notatników innych użytkowników i modyfikowania ich na własny użytek… ciekawe?

Pierwszy notatnik który przygotowałem: https://observablehq.com/@lbacik/untitled (za nic nie udało mi się przemianować tego „untitled” na „gls” – bug?)

Nie jest on zbyt skomplikowany – zawiera trzy elementy:

1. obiekt GLS (a raczej obiekt Canvas na którym renderowany jest obiekt Gls)
2. import fabryki GLSFactory z biblioteki Gls – w formie modułu UMD i z wykorzystaniem Unpkg
3. animation loop – potrzebne aby wszystko ładnie działało

Elementy notatnika możemy podglądać i edytować po wybraniu opcji „edit” z menu kontekstowego elementu, dostępnego po najechaniu na „trzy kropki”, które pojawiają się gdy kursor przesuniemy blisko lewej strony elementu).

Podglądając np. drugi element:

GlsFactory = class

Powinniśmy zobaczyć następujący kod:

GlsFactory = require('https://unpkg.com/@lbacik/gls/dist/gls.js')

Wygląda znajomo?

Observable automatycznie wykonuje kod, który umieszczamy w notatniku, tak więc nasz notatnik staje się… aplikacją. Jeżeli teraz otworzymy pierwszy z elementów i zaczniemy modyfikować kod naszego obiektu Gls (json) to efekt zobaczymy od razu po „przesłaniu/wgraniu” zmian (symbol “strzałki”, jak na klawiszu play w odtwarzaczach, widoczny w prawym-górnym rogu edytowanego elementu notatnika).

Problem, którego na razie nie udało mi się rozwiązać w zadowalający sposób to sposób prezentacji – czegoś tutaj jeszcze brakuje, czegoś dzięki czemu można by było bardziej „swobodnie” zarządzać położeniem elementów notatnika, choć, nawet bez tego, myślę, że jest świetnie!

Powrócę jeszcze do tego serwisu w jednym z kolejnych paragrafów.

Baza Danych

Baza danych przyda się, abyśmy nie musieli publikować nowej wersji Gls-Web za każdym razem, gdy chcemy pochwalić się nowym obiektem Gls (które to obiekty aktualnie są „przechowywane” jedynie jako pliki json w katalogu examples projektu Gls-Web). Dzięki wykorzystaniu bazy zyskamy centralne repozytorium dla naszych plików json!

Po bazę, (śladami MPJ), udałem się do Googla – mamy tutaj interesującą opcję NoSQL – Firebase!

Aktualnie możemy korzystać z dwóch „wersji” usługi firebase

1. Realtime Database – kto nie słyszał, niech się nie martwi, bo ta wersja określona jest już jako „przestarzała”
2. Cloud Firestore – nowa odsłona

Dla mnie przy wyborze najważniejsze były limity przy planie free i tutaj (jakżeby inaczej) – Realtime Database, jako technologia „przestarzała”, daje poszaleć znacznie bardziej. Tak więc wybór padł właśnie na tę wersję!

Realtime Database to tak naprawdę… plik json! Choć w rzeczywistości to nie jest aż tak proste, bo możemy definiować zasady dostępu do poszczególnych elementów (węzłów) naszego pliku (naszych danych), metody uwierzytelnienia czy walidację – ogólnie można wykazać się inwencją, ja jednak ograniczę się do minimum (choć opcja walidacji przesyłanych danych jest kusząca i może do niej wrócę w przyszłości).

Polecam założyć konto i wypróbować usługę – interfejs jest bardzo przystępny i obsługa bazy nie powinna sprawiać dużych kłopotów.

Ponieważ dostęp bezpośredni może być trochę kłopotliwy dla klientów (Gls-Web i Observable) i w sumie powodował by duplikację kodu, dlatego realizowany będzie przez API (Gls-Db-Api). Dodam również klienta (Gls-Db-Api-Client), aby miało to bardziej „zwięzłą” formę, i aby dany serwis mógł praktycznie od razu wywoływać metody pobierające bądź przesyłające dane do bazy.

Serverless – starcie drugie

I kolejne starcie z Serverless – tym razem sięgnijmy po Heroku (oczywiście wybieram plan free) – po sklonowaniu źródeł Gls-Db-Api, Api może zostać udostępnione za pomocą poleceń (informacje w dokumentacji: https://devcenter.heroku.com/articles/container-registry-and-runtime):

 $ heroku container:login
 $ heroku create
 $ heroku container:push web
 $ heroku container:release web

W przypadku kontenera wrzuconego przeze mnie adres został wpisany do schematu aplikacji w Miro – link do api kryje się w „chmurce” „Gls-Db-Api Hosting”.

Akcje takie jak `list` i `get` powinny być dostępne z poziomu przeglądarki (wykorzystują metodę GET protokołu HTTP):

https://API-URL/list – zwróci tablicę elementów Gls w bazie (format json)
https://API-URL/get/gls01 – zwróci konkretny obiekt json z bazy – w tym przypadku: 'gls01′

Oczywiście są różnice w stosunku do OpenShift – nie korzystamy tutaj z kontenera pobieranego ze zdalnego repozytorium (Docker Hub), tutaj budujemy taki kontener lokalnie (w swoim lokalnym systemie) a następnie wysyłamy go do serwisu heroku. Aby móc tę operację przeprowadzić musimy zainstalować klienta cli serwisu heroku. Ponadto, w odróżnieniu od OpenShift, nasza aplikacja domyślnie dostępna jest poprzez połączenie szyfrowane (https) – w przypadku OpenShift musielibyśmy sami wygenerować certyfikat i dodać go w konfiguracji routingu – nie jest to wielka filozofia, ale zawsze kilka rzeczy dodatkowych do zrobienia. Co jednak tutaj istotne, w przypadku Gls-Web, ssl nie jest dla nas specjalnie istotny, natomiast w przypadku Gls-Db-Api, w związku z danymi użytkownika wymaganymi przez akcję „add”, szyfrowanie jest już wskazane! Dodatkowo, wykorzystanie protokołu https w komunikacji ze zdalnymi serwisami jest wymagane przez serwis Observable (Observable będzie się łączyć z Gls-Db-Api wykorzystując Gls-Db-Api-Client) – połączenia korzystające z protokołu http są blokowane!

Observable DB

Wersja notatnika korzystająca z bazy to fork notatnika opisanego w poprzednim paragrafie o Observable – dodałem jedynie formatkę, służącą do wysyłania (za pomocą Gls-Db-Api-Client) edytowanego obiektu Gls do bazy. Przydałoby się tutaj jeszcze trochę pracy – nie działa to idealnie, ale dane są przesyłane i zapisywane, więc jest ok przynajmniej z technicznego punktu widzenia!

Oczywiście możliwość zapisu jest zabezpieczona hasłem, więc aby przeprowadzić własny test trzeba skonfigurować bazę i wystawić gdzieś endpoint API – ważne, aby komunikacja była po https (pal licho hasła, ale observable po prostu będzie blokował komunikację nieszyfrowaną).

Ostatnia rzecz to kwestia CORS – kod definiujący połączenie do API wygląda następująco (element poniżej formularza):

const dbapi = GlsApiClient.create('https://cors-anywhere.herokuapp.com/' + dbUrl)

Usługa https://cors-anywhere.herokuapp.com rozwiązuje problem przy małym natężeniu ruchu, więcej informacji jest w tym notatniku – również jak skonfigurować whitelistę po stronie heroku.

Podsumowanie

I w sumie to już koniec tej „wycieczki” – aplikacja Gls działa i jest dostępna (wczytywanie obiektów z bazy niekiedy trwa trochę długo, ale cóż – to są minusy, z którymi należy się liczyć w tego typu implementacjach).

Niestety nie udało mi się tutaj poruszyć wszystkich tematów, które wynotowałem sobie w pierwszym szkicu tego artykułu. Tak jak wspominałem już na początku, takie rzeczy jak CI/CD czy Load Balancing musiałem porzucić (zgodnie ze „zwinną” wersją „żelaznego trójkąta”). To oznacza, że eksperyment można kontynuować i rozszerzać jego funkcjonalność – zachęcam do tego w wolnych chwilach (w ramach swoich własnych mini-projektów, bądź w ramach Gls!). W końcu „praktyka” to podstawa, a jak się okazuje, aby podnosić nasze devopsowe umiejętności, wcale nie musimy dysponować dostępem do (jakiejkolwiek) serwerowni – wystarczy dostęp do Internetu!

Autorem tekstu jest Łukasz Bacik.

#244 Fake newsy i ich wpływ na wizerunek marki

Pamiętacie tygodnik „Skandale”? To taki brukowiec, który w latach 1990-1994 rozpalał wyobraźnię wielu Polaków. Można go nazwać klonem „The Weekly World News”, amerykańskiego czasopisma, które publikowało wyssane z palca ciekawostki. Określenie ‘ciekawostki’, to w tym kontekście pewne nadużycie, bo chodzi o sensacyjne newsy jak to, że Elvis żyje, a Hillary Clinton zaadoptowała dziecko kosmitów. Takie bzdury w czasach ograniczonego dostępu do sieci były podwalinami pod współczesne fake newsy. Nastała epoka deep fake, epoka postprawdy, która pokazuje, jak bardzo chętnie wierzymy w bzdury, treści niesprawdzone, obraźliwe, często atakujące inne osoby. Czytaj dalej

SOAP vs REST

Wymiana danych i integracja z zewnętrznymi systemami jest nieodłącznym elementem wszystkich złożonych aplikacji. Aby była możliwa, konieczne jest określenie konkretnych reguł i formatów komunikacji. Te zasady mogą określać protokoły komunikacji, czy też usystematyzowane struktury danych, artykuł skupi się na dwóch z nich: SOAP oraz REST.

SOAP (Simple Object Access Protocol) – protokół stworzony głównie na potrzeby Microsoftu w 1998 roku, w związku z zapotrzebowaniem na umożliwienie komunikacji pomiędzy aplikacjami z użyciem języka XML. Nadal szeroko używany, głównie ze względu na standaryzację, bezpieczeństwo i prostą kontrolę nad zawartością przekazanych danych.

REST (Representational State Transfer) – styl architektoniczny definiujący format przesyłanych danych, utworzony w 2000 roku przez Roya Fieldinga w ramach rozprawy doktorskiej, jako element standaryzacji protokołu HTTP. Używany ze względu na elastyczność, szybkość i prostotę. Nie jest protokołem – jako usługę RESTową można zdefiniować cache’owany, bezstanowy, komunikujący się na zasadzie klient-serwer serwis.

Format

Mnogość dostępnych formatów danych zdecydowanie przemawia na korzyść REST. Poza wiodącym JSONem, dane można wymieniać m. in. w formatach HTML, XML, YAML, czy nawet jako zwykły tekst. SOAP natomiast umożliwia komunikację jedynie z użyciem XML. Ograniczeniem RESTa jest natomiast jeden protokół – HTTP. SOAP możliwy jest dla ich szerszej gamy – m. in. HTTP, SMTP, czy UDP.

Bezpieczeństwo

SOAP wykorzystywany jest często ze względu na znaczące ułatwienia dotyczące bezpieczeństwa. Zaletami będą tutaj wsparcie dla WS-Security (rozszerzenie o elementy bezpieczeństwa, zapewniający integralność, poufność czy dołączanie tokenów do komunikatów), wbudowana logika wspomagająca komunikowanie błędów w integracji, czy łatwiejszą komunikację poprzez firewall oraz proxy. Jeśli chodzi o REST, wdrożenie analogicznych rozwiązań może być mniej wygodne. Oba rozwiązania oczywiście wspierają SSL.

Rozmiar danych

Wymuszenie przez SOAP formatu XML oraz określonych definicji w dokumencie powoduje narzut na przesyłane zapytanie. Dostępne dla REST formaty, takie jak JSON, czy YAML, mimo że mniej ustandaryzowane, jeśli chodzi o rozmiar są zdecydowanie bardziej optymalne. Różnica w rozmiarze (XML vs JSON) dla testowanych danych [6)] wyniosła około 25%.

Wydajność

REST trzeba uznać za zdecydowanie wydajniejszy. W związku z mniejszym rozmiarem wymaga mniejszej przepustowości łącza. Dla tej samej ilości danych potrzebuje również mniejszej mocy obliczeniowej. Aspekty te powodują szybsze działanie RESTa, nawet o kilkadziesiąt procent. REST również, w przeciwieństwie do SOAPa umożliwia cache’owanie wywołań API.

Zastosowanie

Funkcjonalnie patrząc, praktycznie każdą usługę sieciową można oprzeć zarówno na SOAP, jak i na REST. Z uwagi na wydajność i wygodę, obecnie zdecydowanie częściej korzysta się z RESTful API. Część istniejących już webserwisów opartych na SOAP, jest przepisywana na REST, pomimo próby zachowania obecnej funkcjonalności. Zastosowanie SOAPa jest bardziej wyspecjalizowane i może mieć on przewagę dla aplikacji, w których kluczowe jest bezpieczeństwo, jak np. różne usługi finansowe, bramki płatności.

Stanowość

Jednym z założeń RESTa jest komunikacja bezstanowa, co skutkuje brakiem tworzenia czy przechowywania sesji po stronie serwera, co wpływa korzystnie na łatwość powiększania systemu, czy jego modernizację. SOAP może działać zarówno bezstanowo, jak i z wykorzystaniem sesji.

Dane

REST traktuje dane jako zasoby; udostępnione one są za pomocą standardu URI (Uniform Resource Identifier), konkretne zasoby bywają w praktyce opisane w dokumentacji serwisu. SOAP udostępnia elementy logiki aplikacji jako usługi, definiowane według standardu WSDL opracowanego przez Microsoft i IBM. Plik definiuje, jakie informacje i w jaki sposób można wydobyć z serwisu.

Podsumowanie

Podsumowując, pomimo słabnącej popularności usług opartych na protokole SOAP i wielu zalet RESTa, nie jest możliwe jednoznaczne wybranie uniwersalnego lepszego rozwiązania. Dobór trzeba rozważyć zależnie od wdrażanej aplikacji – i mimo że w większości sytuacji najprawdopodobniej będzie to REST, SOAP nadal może okazać się przydatny.

Autorami tekstu są Łukasz Kowol i Jakub Sładek.

Źródła:
1) https://www.pearsonhighered.com/assets/samplechapter/0/6/7/2/0672326418.pdf
2) https://raygun.com/blog/soap-vs-rest-vs-json/
3) https://en.wikipedia.org/wiki/Representational_state_transfer
4) https://stackify.com/soap-vs-rest/
5) http://edu.pjwstk.edu.pl/wyklady/tbo/scb/lecture-13/lecture-13-content.html
6) https://aaltodoc.aalto.fi/bitstream/handle/123456789/29224/master_Makkonen_Joni_2017.pdf?sequence=1&isAllowed=y
7) https://www.guru99.com/comparison-between-web-services.html

ORI – czy Twój biznes jest gotowy na omnichannel?

Pojęcie omnichannelu znamy już właściwie wszyscy, nie tylko w teorii, ale również w praktyce. Taka synergia wszystkich, wykorzystywanych przez markę kanałów komunikacji, zarówno online jak i offline to jednak coś więcej niż tylko nośne hasło. To idea, wokół której kształtują się całe biznesy, branże, a nawet rynki. Idea, której wdrożenie już jakiś czas temu stało się biznesową koniecznością. Detaliści z całego świata nieustannie pracują nad tym, aby przekształcać swoje relacje z klientami, oferując im w tym celu zakupy w modelu omnichannel, dzięki czemu mogą oni sami kształtować swoje procesy zakupowe. Czy jednak każdy biznes jest gotów na wdrożenie omnichannelu? Czy w każdym przypadku zakończy się to sukcesem? Jak się o tym przekonać?

ORI – podstawy teoretyczne

Aby uzyskać odpowiedzi na te i wiele innych pytań, opracowany został specjalny wskaźnik – Omnichannel Readiness Index (ORI). W metodyce badawczej przyjętej przez PWC – globalne przedsiębiorstwo świadczące usługi księgowe, audytorskie i doradcze – rolą ORI jest pomiar potencjalnych szans nie tylko zaistnienia, ale również odniesienia sukcesu w omnichannel ecommerce, a także oszacowanie poziomu dojrzałości danej jednostki (niezależnie czy będzie to konkretna branża, czy jakiś wybrany rynek) do wdrożenia tej idei w życie. Wskaźnik ten został stworzony, jako wypadkowa ocen czterech, niezależnych czynników. Pierwszy z nich to zachowania konsumenckie, a dokładniej stopień, w jakim klienci zamieszkujący dany kraj realnie wykorzystują ideę omnichannel do realizacji swoich zakupów detalicznych. Czynnik drugi stanowi poziom digitalizacji kanałów sprzedaży, który określany jest jako połączenie zakupów internetowych oraz zakupów mobilnych i rozpatrywany jest w ujęciu konkretnego kraju i segmentu detalicznego. Jako trzeci wymieniany jest potencjał omnichannel, czyli szacowana możliwość wzrostu sprzedaży mobilnej i internetowej w danym obszarze, z kolei ostatni, czwarty element to infrastruktura ukazująca wzajemne przenikanie i uzupełnianie się urządzeń i usług omnichannel.

ORI w praktyce

Aby przekonać się, jaki jest rzeczywisty stopień gotowości do wdrożenia idei omnichannel, PWC przebadało 9 segmentów, takich jak:
elektronika użytkowa,
rzeczy z kategorii “zrób to sam” oraz te związane z domowymi naprawami,
sklepy spożywcze,
tradycyjne zabawki i gry,
odzież i obuwie (w tym również sprzęt sportowy i produkty z kategorii outdoor),
produkty multimedialne,
wyposażenie domu i AGD,
przedmioty użytku osobistego i okulary,
pielęgnacja urody, higiena osobista oraz opieka zdrowotna

Analizie poddanych zostało 19 krajów i regionów, wśród których znalazły się: Szwajcaria, Chile, Turcja, Indie, Stany Zjednoczone, Wielka Brytania, Dania, Kanada, Chiny, Belgia, Japonia, Australia, Francja, Włochy, Niemcy, Rosja, Południowa Afryka, Brazylia oraz Bliski Wschód.

Wyniki przeprowadzonych badań okazały się dość interesujące. Za kraje, w których omnichannel odgrywa największą rolę uznane zostały Stany Zjednoczone, Wielka Brytania i Australia. Nie stanowi to jednak zaskoczenia, biorąc pod uwagę fakt, że to właśnie w tych krajach handel elektroniczny jest najbardziej powszechny i dojrzały. Co jednak ciekawe, badane kraje europejskie plasują się mniej więcej po środku całej skali, co oznacza, że pomimo prężnie rozwijającej się tam sprzedaży internetowej, sam omnichannel jest w nich jeszcze dość mocno ignorowany. Kraje, które multikanałowość mają rozwiniętą w najmniejszym stopniu i równocześnie są najmniej gotowe na jej wdrożenie to Indie, Afryka czy Brazylia co niewątpliwie skorelowane jest z ich niskim poziomem ogólnego rozwoju technologicznego.

Jeśli chodzi o konkretne kategorie produktowe, najsilniejsze pozycje w omnichannel zajmują: elektronika użytkowa, produkty multimedialne oraz odzież i obuwie (w tym również sprzęt sportowy i produkty z kategorii outdoor) – są to więc kategorie produktów użytku codziennego, których zakup wymaga relatywnie większych nakładów finansowych, co powoduje, że podjęcie decyzji o zakupie tego typu produktów staje się dość trudne. Aby ułatwić klientom zakup tych dóbr, marki muszą wyjść naprzeciw ich oczekiwaniom, co w efekcie powodować może wdrożenie takich rozwiązań, jak choćby właśnie omnichannel. Najsłabszy udział w omnichannel odnotowuje z kolei branża spożywcza, produkty przeznaczone do pielęgnacji urody, higieny osobistej oraz opieki zdrowotnej, a także przedmioty użytku osobistego i okulary. Co ciekawe – produkty z tych kategorii również wykorzystywane są w użytku codziennym, jednak, w większości przypadków, ich ceny są znacznie niższe, niż w przypadku kategorii najsilniej reprezentowanych w omnichannel. Mały udział tych segmentów w omnichannel może jednak, w niedalekiej przyszłości stanowić dużą szansę na rozwój – to obszary, które dotąd nie zostały zbyt dobrze zagospodarowane, przez co, przy odpowiednim przygotowaniu technologicznym, mogą one stanowić świetną drogę do wyróżnienia się na rynku, a co za tym idzie, zwiększenia poziomu sprzedaży.
Obok założeń przyjętych przez PWC, ciekawe wydają się także te przyjęte przez Instytut badawczy Statista (działający we współpracy z niemieckim koncernem usługowym WISAG). Według nich, ORI pozwala nie tylko zweryfikować samo istnienie (lub potencjał wdrażania) systemów typu omnichannel w danej jednostce, ale również umożliwia usytuowanie tych systemów w kontekście percepcji i preferencji klientów. Oceniane są tu czynniki takie jak zakres oferty usług oraz opinia klienta. Tylko odpowiednie skorelowanie ze sobą tych dwóch aspektów pozwoli na realną ocenę tego, jak poszczególne usługi postrzegane są przez klientów i które z tych dostępnych na rynku mają dla nich większą wartość niż inne. Analizy oparte na tych dwóch czynnikach pozwalają na wyróżnienie czterech rodzajów firm. Pierwszy to tak zwani mistrzowie cyfryzacji, czyli firmy osiągające ponadprzeciętne wyniki w obu kategoriach, mające szeroką ofertę usług, która spotyka się z bardzo dobrymi opiniami klientów. Drugi rodzaj to cyfrowi entuzjaści, czyli te firmy, które pomimo tego, że w zakresie swojej oferty mocno wybijają się ponad średnią, to w kwestii pozytywnej percepcji i wpasowania się w preferencje klientów wciąż jeszcze mają sporo pracy do wykonania. Kolejno wymieniani są cyfrowi oportuniści, którzy uzyskują pozytywne oceny wśród klientów, jednak mają problem z zagwarantowaniem im odpowiedniego zakresu oferty. Ostatnią kategorię stanowią firmy, które dopiero zaczynają swoją działalność w cyfrowym świecie i wykazują deficyt w obu ocenianych aspektach.

Szanse i zagrożenia

Znajomość rynków oraz potencjału kategorii produktowych zdecydowanie pomaga we wdrożeniu strategii omnichannel, niestety jednak, sama w sobie nie jest wystarczająca. Aby stać się mistrzem cyfryzacji konieczne jest także spełnienie trzech, kluczowych dla powodzenia strategii omnichannel warunków.

Pierwszy z nich to udoskonalona infrastruktura techniczna, która wymaga nieustannego rozwoju, zarówno w obszarze sieci urządzeń, jak i samej komunikacji pomiędzy nimi. Drugi czynnik to spełnienie wysokich oczekiwań klientów, którzy domagają się wszystkiego tego, co najlepsze w obydwu światach. Oczekują oni przede wszystkim doradztwa i natychmiastowej dostępności produktów charakterystycznych dla kanału offline oraz przejrzystości cen, szerokich możliwości porównywania produktów i wygodnych form płatności cechujących kanał online. Trzeci, ostatni już czynnik, stanowi pełna gotowość sprzedawcy do przyjęcia modelu omnichannel, wymagająca wdrożenia odpowiedniej kultury korporacyjnej, traktującej offline i online jako jeden podmiot – zarówno pod kątem samych strategii sprzedaży jak i biznesu w ogóle.

Co ciekawe, jak pokazują raporty, o ile dla większości firm wdrożenie nowoczesnej infrastruktury technicznej i jej ciągłe udoskonalanie jest czymś wręcz naturalnym, o tyle gotowość detalistów do wdrożenia tej strategii, czy umiejętność skupienia się na potrzebach i doświadczeniach klientów wciąż stanowią duże wyzwanie. To właśnie to sprawia, że tak wiele firm zaliczanych jest do kategorii cyfrowych oportunistów.

Szybki rozwój technologiczny sprawia, że poziom wyrafinowania, wygody, kreatywności i ogólnej wartości podejścia omnichannel nieustannie wzrasta. Doszliśmy już do takiego momentu rozwoju rynku, w którym granica między offline a online zaciera się coraz mocniej. Omnichannel retailing jest obecnie standardem rynkowym, sposobem dokonywania zakupów, który w żaden sposób nie wyróżnia już marki na rynku, natomiast którego brak może przysporzyć marce wielu problemów.

#243 Raport – Multiwyzwania 2018

Platforma Shoper opublikowała raport, który skupia się na branży e-commerce 2018. To dość ciekawa analiza 445 sklepów korzystających z rozwiązań tej marki. Analiza ta daje dość ciekawy obraz e-sklepów, działań właścicieli i wybieranych przez nich rozwiązań, które ich zadniem mają wpływ na sprzedaż. Pokusiliśmy się na małą analizę tego dokumentu, bowiem znajduje się w nim kilka bardzo ciekawych danych. Czytaj dalej

#242 Logistyka w polskich e-sklepach – raport 2018 | Średnia cena przesyłki w Europie – badanie

Specjaliści z furgonetka.pl po raz trzeci postanowili przeanalizować rodzimy rynek logistyki w e-commerce. Dzięki temu powstał raport pokazujący, jakie rodzaje dostaw możemy znaleźć w sklepach internetowych. Analiza obejmowała dwa rodzaje sklepów te małe i średnie oraz duże. Przyjęto, że duży sklep internetowy to taki, który nadaje ponad 150 przesyłek dziennie. Każdy z tych sklepów został przebadany pod kątem ilości dostępnych w nich form dostawy, oferowanych w nich firm kurierskich oraz kosztów doręczenia. Dodatkowo pokazujemy także inne badanie przeprowadzone przez Sellics, które pokazuje średnie ceny przesyłek w Europie. Czytaj dalej

Efekt ROPO – co może zagwarantować Twojej firmie?

Relacje między marką a klientem zmieniają się bardzo dynamicznie. Współcześnie są one zupełnie inne niż 5, 10, czy 20 lat temu. Na ich kształt wpływa bardzo wiele czynników, jak np. ilość i jakość dostępnych na rynku towarów, czy choćby nieustannie rosnące potrzeby konsumenckie. Kolejne pokolenia kupujących są coraz bardziej świadome swoich potrzeb, ale też coraz bardziej wymagające. Marka, żeby nie dać się wyprzedzić konkurencji oraz na stałe wpisać się w umysły klientów, musi przyjąć szybkie tempo działania oraz na bieżąco dostosowywać swoją aktywność do rosnących wymagań rynku. Pierwszym krokiem ku temu może być odpowiednie wykorzystanie efektu ROPO, czyli zachowania klientów, polegającego na poszukiwaniu informacji o produkcie czy usłudze w Internecie, a następnie finalizacji zakupu w sklepie stacjonarnym.

Pokaż mi swój koszyk, a powiem Ci kim jesteś

Raport “Efekt ROPO w segmentach polskiego e-commerce – 2015”, przeprowadzony i opublikowany przez platformę badania satysfakcji – opiniac.com, definiuje współczesnego klienta jako osobę mieszkającą w dużym mieście, posiadającą wykształcenie wyższe magisterskie lub równorzędne oraz korzystającą codziennie lub prawie codziennie z Internetu. Według raportu “E-commerce w Polsce”, przeprowadzonego przez międzynarodową firmę badawczo-technologiczną Gemius, współcześni konsumenci najchętniej kupują online produkty takie jak: ubrania, książki, filmy, bilety do kina oraz teatru.

Powszechny dostęp do Internetu sprawia, że oczekiwania klientów ewoluują, a marki otrzymują coraz szersze możliwości, w postaci nowych szans komunikacyjnych, wizerunkowych i sprzedażowych.

Współczesny konsument to zatem taki z laptopem lub smartfonem w ręku, w pełni świadomy oferty produktowej, dostępnej zarówno w Internecie, jak i sklepach stacjonarnych. Do najczęściej wymienianych zachowań współczesnych internautów należą: poszukiwanie produktów i marek, porównywanie cen produktów i usług, kupowanie produktów i usług na polskich stronach internetowych, czy poszukiwanie sklepów, które chce się odwiedzić.

Synergia online i offline gwarantem sukcesu

Odpowiednie połączenie kanału online z kanałem offline stanowi co prawda nie lada wyzwanie, jednak zdecydowanie jest to działanie, które warto podjąć. Dzięki temu, marka ma możliwość zbudowania pozytywnych doświadczeń swoich klientów, niezależnie od tego, z jakich kanałów sprzedażowych korzystają oni w danej chwili.

Taka multikanałowość kojarzona jest przede wszystkim z: efektem ROPO oraz odwróconym efektem ROPO, czyli dwoma, powszechnie spotykanymi praktykami zakupowymi. Efekt ROPO (Research Online Purchase Offline), zwany też webroomingiem, to możliwość zapoznania się z produktem i jego parametrami online (przez sklep internetowy lub aplikację mobilną), a następnie dokonanie jego zakupu już offline (w jednym z salonów stacjonarnych marki). Z kolei efekt odwróconego ROPO (Research Offline Purchase Online), czyli showrooming, to możliwość weryfikacji produktów “na żywo”, a następnie dokonanie ich zakupu już w świecie wirtualnym.

Obydwa kanały – online i offline, oprócz szeregu możliwości i szans sprzedażowych posiadają też pewne wady. Odpowiednie ich połączenie pozwala jednak na maksymalne wykorzystanie ich zalet oraz minimalizację ograniczeń. Dzięki synergii online i offline, klientom zagwarantowana jest zupełnie nowa, wyższa jakość doznań zakupowych. Połączenie tych kanałów nazywane jest omnichannelem i pozwala klientowi na zrealizowanie jego najważniejszych potrzeb, takich jak:
– weryfikacja produktu online oraz jego zakup offline
– weryfikacja produktu offline oraz jego zakup online
– zakup produktu online oraz jego odbiór offline
– zakup produktu online oraz jego zwrot offline

ROPO a sukces biznesowy

Zmiany technologiczne stanowią dla marek ogromną szansę biznesową. Zrozumienie efektu ROPO i odwróconego efektu ROPO to dobry początek, aby podjąć szereg inicjatyw cyfrowych. Dobrze rozwinięty kanał online stanowić będzie świetne wsparcie dla tradycyjnego biznesu i umożliwi firmie zdobycie kolejnych klientów i zbudowanie solidnych przewag konkurencyjnych. Sukces w czasie e-rewolucji wymaga jednak od marki sporych nakładów pracy – od szczegółowej analizy jej pozycji konkurencyjnej, aż po weryfikację potencjału biznesu w obszarach takich jak: strategia, kompetencje, kultura oraz organizacja.

Efekt ROPO, tak jak i efekt odwróconego ROPO, nie są czymś, czego należy się obawiać. Wystarczy tylko zwrócić uwagę na to aby:
– publikować wyłącznie rzetelne, spójne dla wszystkich kanałów treści
– dostosować system sprzedaży do różnych rodzajów urządzeń
– zdobyć i wykorzystać wiedzę o zachowaniach zakupowych klientów dzięki zastosowaniu marketing automation
– zaoferować klientom atrakcyjną oraz spójną dla online i offline politykę zwrotów i reklamacji
– zadbać o wygodną i szybką dostawę

Cyfrowi liderzy to firmy, które umiejętnie wykorzystały potencjał nowych technologii. Charakteryzuje ich szybkość, elastyczność, brak obawy przed porażką, chęć nauki i testowania nowych rozwiązań oraz umiejętność współpracy. Co zrobić, aby stać się jednym z nich? Przede wszystkim zaprojektować, a następnie wdrożyć dobrą, dostosowaną do konkretnego rynku i branży strategię omnichannel.

Duże tablice. Jak je ugryźć?

Generator

Każdy programista w swojej pracy boryka się z problemami związanymi z użyciem pamięci. Czasami urwanie 1mb jest na wagę złota i od tego może zależeć poprawne wykonanie skryptu.

Najczęstszym problemem jest procesowanie tablic zawierających tysiące rekordów. Na szczęście z pomocą przychodzi Generator. Jest to funkcja, która pozwala na iterowanie po zbiorach danych. W PHP został dodany w wersji 5.5. Aby zacząć używać funkcji Generatora wystarczy zamiast return użyć yield.

function getData()
{
	for ($i = 0; $i < 100000; $i++)
	{
		yield $i;
	}
}

$data = getData();

Funkcja getData() zwraca obiekt klasy Generator, która implementuje interface Iterator.

Dzięki temu tablica nie jest od razu budowana w pamięci, a my mamy możliwość iterowania po rekordach.

Test

Jak wygląda kwestia wydajności? Przeprowadziłem 2 testy. Jedno przy użyciu PDO i tabeli zawierającej ok 200k rekordów oraz z tablicą również zawierającą ok 200k rekordów.

<?php
class TestGenerator
{
	private $pdo;

	public function __construct()
	{
		$this->pdo = new PDO(
			'mysql:host=127.0.0.1;dbname=test;port=3300',
			'root',
			'root'
		);
	}

	public function pdoWithGenerator()
	{
		$stmt = $this->pdo->query('select id from `test`');

		while ($row = $stmt->fetch())
		{
			yield $row;
		}
		echo 'PDO Generator: ' . round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
	}

	public function pdoWithoutGenerator()
	{
		$stmt = $this->pdo->query('select id from `test`');

		$test = [];
		while ($row = $stmt->fetch())
		{
			$test[] = $row;
		}
		echo 'PDO Brak generatora: ' . round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
		return $test;
	}

	public function testArrayWithGenerator()
	{
		for ($i = 0; $i <= 200042; $i++)
		{
			yield $i;
		}
		echo 'Tablica Generator: ' . round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
	}

	public function testArrayWithoutGenerator()
	{
		$test = [];
		for ($i = 0; $i <= 200042; $i++)
		{
			$test[] = $i;
		}
		echo 'Tablica brak generatora: ' . round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
		return $test;
	}
}

$test = new TestGenerator();

foreach ($test->pdoWithGenerator() as $item){}
foreach ($test->pdoWithoutGenerator() as $item){}
foreach ($test->testArrayWithGenerator() as $item){}
foreach ($test->testArrayWithoutGenerator() as $item) {}

Podsumowanie

Wnioski z tego testu są dość oczywiste. Jak widać powyżej, używając Generatora można zaoszczędzić znaczną ilość pamięci.

Ciekawostki:
* Można wykonywać operacje po yield, np. za pomocą break.

function getData()
{
	for ($i = 0; $i < 100000; $i++)
	{
		yield $i;

		if ($i === 10)
		{
			break;
		}
	}
}

$data = getData();

foreach ($data as $i)
{
	echo $i. PHP_EOL;
}

* Można zwracać pary klucz-wartość.

function getData()
{
	for ($i = 0; $i < 10; $i++)
	{
		yield $i => $i+1;
	}
}

$data = getData();

foreach ($data as $key => $value)
{
	echo 'Key: ' . $key . PHP_EOL;
	echo 'Value: ' . $value . PHP_EOL;
}

Autorem tekstu jest Łukasz Cieślik.