Autor: Adam Trojnar

Dwu argumentowy predykat, funkcja, konsument. Opis i porównanie

W poście tym przybliżam ciekawą funkcję wprowadzoną w Java8 jaką jest umożliwienie wprowadzania dwóch argumentów do Predykatu, Funkcji, Konsumenta i Dostawcy.

1. Predykat (Predicate)

Jest to funkcja, która przyjmuje jakiś argument i odpowiada: „tak” lub „nie”, w zależności od podanego jej elementu. Przykład predykatu jedno argumentowego gdzie sprawdzamy czy zmienna jest parzysta lub nie:
Predicate<Integer> p = i-> i%2==0;
W przypadku gdy predykat zwróci „tak”, to metoda umieści ten element w kolekcji wynikowej. W przeciwnym razie, ten element się tam nie znajdzie.

BiPredicate daje nam możliwość sprawdzenia warunków dla 2 argumentów. Poniżej przykład użycia:

import java.util.function.*
class Test {
public static void main(String [] args){
        BiPredicate<Integer, Integer> p = (a,b)  ->  (a+b) % 2  == 0;
        log.debug(p.test(10,20); // true
        log.debug(p.test(15); // false
    }
}

2. Funkcja

Przykład użycia funkcji gdzie na wejściu podajemy jeden argument typu Integer. W wyniku wykonania funkcji zwracamy mnożenie arguemntu prez samego siebie. Czyli jest to
function <Integer, Integer> f = i -> i*i

BiFunkcja w odróżnieniu od funkcji przedstawionej powyżej może na wejściu przyjąć 2 wartości i je przetworzyć.  Poniżej przykład użycia:

import java.util.function.*
class Test {
public static void main(String [] args){
        BiFunction<Integer, Integer, Integer> f = (a,b) -> a*b
        log.debug(p.apply(10,20); // 200
        log.debug(p.apply(1, 10); // 10
    }
}

3 Konsument

Przykład użycia konsumenta gdzie na wejściu przyjmujemy argument typu String. Następnie przekazujmy go do funkcji sopen.
Consumer<String> c = a -> sopen(a)

BiKonsument może przetworzyć na wejściu 2 argumenty.

Przykład użycia BiFunction oraz BiConsumer:
import java.util.function.*;
import java.util.*
class Employee {
    String name;
    double salary;

Employee(String name, double salary){
    this.name = name;
    this.salary = salary;
}
class Test {
    public static void main(String[] args){
        ArrayList<Employee> list = new ArrayList<Employee>();
        BiFunction<String, double, Employee> f = (name,salary) -> new Employee(name, salary);

    list.add(f.accept(„Adam”, 1000000000));
    list.add(f.accept(„Ada”, 1000));
    list.add(f.accept(„Anna”, 1000));

BiConsumer<Employee, Double> c = (e,d) -> e.salary = e.salary + d;

for (Employee e: list){
    c.accept(e, 600);

}

    for (Employee e :l){
        log.debug(e.salary);
        log.debug(e.name);
    }
    }
}

4. Dostawca (Supplier)

Zwraca (dostarcza) wartość typu Date.

Supplier<Date> s = () -> new Date();

Porównanie jedno i dwu argumentowego predykatu i funkcji:

Jedno argumentowy interfejs funkcjonalny. 
interface Predicate<T> {
    public boolean test(T t);
    default Predicate and(Predicate p);
    default Predicate or(Predicate p);
    default Predicate negate();
    static Predicate isEqual(Object o);
}

Zawiera jedna metodę abstrakcyjna (test) oraz 4 domyśle metody i jedna metodę statyczna.


Dwu argumentowy interfejs funkcjonalny:

interface BiPredicate<T, U> {
    public boolean test(T t, U u);
    default BiPredicate and(BiPredicate p);
    default BiPredicate or(BiPredicate p);
    default BiPredicate negate();
}
Nie posiada metody statycznej. Przyjmuje 2 argumenty w metodzie abstrakcyjnej.
Interfejs Funkcji:
interface Function<T,R> {
    public R apply(T t);
    default Function andThen(Function f);
    default Function compose(Function f);
          static Function identity();
}
Posiada jedne argument na wejściu (T) oraz zwraca jeden argument (R). Jedna metode abstrakcyjna oraz 2 domyślne i jedna statyczna.
Interfejs BiFunkcji:
interface BiFunction<T, U, R> {
    public R apply(T t, U u);
    default BiFunction andThen(Function f);
}
Posiada 2 argumenty na wejściu (T,U) oraz zwraca jeden argument (R). Warto zauważyć że domyślna metoda andThen przyjmuje na wejściu Funkcję f a nie BiFunckję.
Jednoargumentowy interfejs Konsument:
interface Consumer<T> {
    public void accept(T t);
    default Consumer andThen(Consumer c);
}
Przyjmuje jeden argument i nic nie zwraca. 
Dwuargumentowy interfejs Konsument:
interface Consumer<T> {
    public void accept(T t);
    default BiConsumer andThen(Consumer c);
}
Przyjmuje dwa argumenty ale nic nie zwraca. Metoda andThen używamy do łaczenia większej ilości Konsumentów.
    

Reactive streams i projekt Reactor ogólne informacje

W tym spisie zebrałem krótkie informacje na temat Reactive streams i project Reactor. Są również bardzo ciekawe linki, które w szybki sposób pomogą Ci wskoczyć na poziom umożliwiający programowanie z użyciem wspomnianych bibliotek.

Elementy występujące w Reactive streams możemy podzielić na:

  1. Publisher
  2. Subscriber
  3. Subscription
  4. Processor

Kiedy Subscriber zaczyna subskrybować Publisher zostaje utworzona Subskrybcja. Subskrybcja jest następnie przesyłana do metody onSubscribe.

Subscriber wysyła rządanie o elementy za pomocą onSubscribe i Publisher wysyła je. W przypadku gdy Publisher nie ma już więcej elementów do wysłania wywołana zostaje metoda onComplete.

W momencie gdy wystąpi błąd, subsrkypcja zostaje przerwana i zostaje wywołana metoda onError.
src: https://github.com/reactive-streams/reactive-streams-jvm


Projekt reactor

Aby nie tracić czasu podaje poniżej przydatne dla mnie informacje, które od razu pokazują jak stosować najbardziej używane elementy projektu Reactor:

  1. Flux
  2. Mono

Są to implementacje, interfejsu Publisher. Powyższe elementy muszą zostać zasubskrybowane. Można na nich operować za pomocą metod np:

  • map
  • flatMap
W źródłach poniżej znajdują się bardzo przydatne informacje na temat praktycznego użycia Reactor. W linku 1 kiedy używać jakiego operatora np. kiedy używać Mono.just a w którym przypadku jest lepszy Optional. Są też podane informacje jak transformować uzyskane dane.
W linku 2 są natomiast podane najlepsze praktyki. Są tam odpowiedzi na pytania np: Jak odebrać i obsłużyć żądanie synchroniczne.
Praktyczne ćwiczenia znajdują się natomiast w Linku 3 . Jest to projekt na GitHubie utworzony przez twórców projektu Reactor. Musimy w nim ukończyć rozpoczęty kod. Jest to wspaniałe ćwiczenie 🙂

src:

  1. https://projectreactor.io/docs/core/release/reference/#which-operator
  2. https://projectreactor.io/docs/core/release/reference/#faq
  3. https://github.com/reactor/lite-rx-api-hands-on



Tworzenie historyjek (stories), co oznacza INVEST oraz 3C

Historyjki użytkownika (User stories) maj swój pocztek w eXtreme Programming. Zespoły SCRUM’owe implementuja w zależności od swojego doświadczenia i potrzeb różne techniki takie jak eXtreme programming, Test Driven Development oraz aktywne programowanie w parach lub całym zespołem przy jednym komputerze.
Dobrze przemyślana historyjka powinna zawierać tytułowe 3C czyli:

  1. Card, 
  2. Conversation, 
  3. Confirmation
Jeżeli chcemy sprawdzić czy historyjka jest poprawnie napisana powinniśmy także rozpatrzyć jej zawartość pod katem INVEST czyli: 
  1. Independent
  2. Negotiable
  3. Valuable
  4. Estimable
  5. Small
  6. Testable

W dalszej treści artykułu dokładniejsze krótkie wyjaśnienie co oznacza skrót 3C.

3C

CARD
Historyjkę możemy tworzyć w postaci karty (lub samoprzylepnej karteczki ;)) np: jako nowe stories w Jira lub po prostu kawałek kartki na ścianie. Historyjka taka powinna mieć powtarzalny szablon, który odpowiada na pytania np.
A) who? what? why?. 
B) I would like it because?
Dzięki takiemu rozwiązaniu nie trzeba się za każdym razem zastanawiać jak zacząć np:
As a <user role> of the product
I can <action>
So that <benefit>
CONVERSATION
Każdy członek zespołu przed rozpoczęciem opisywania historyjki powinien się do niej przygotować na ile jest to możliwe. Im wcześniej mamy potrzebne informacje i dobrze wykorzystany czas na analizę tym mniej zajmie nam implementacja. Więc jeżeli mamy wątpliwości musimy rozmawiać z Właścicielem Produktu i mu oraz całemu zespołowi je przedstawiać. Powinniśmy także zapraszać osoby bezpośrednio związane z historyjka np. osoby z biznesu lub przedstawicieli z innych zespołów.
CONFIRMATION
Właściciel produktu oraz zespół wspólnie zgadzaj się że historyjka jest kompletna i może być poddana implementacji. Muszą ze sobą współpracować pro aktywnie. Historyjka musi zawierać kryteria akceptacji dzięki, którym wszystkie strony będą mogły stwierdzić czy jest ukończona.

Akronim INVEST to:

INDEPENDENT
Historyjki musza być jak najbardziej niezależne. Im mniej zależności np. technicznych tym lepiej
NEGOTIABLE
Wszystko jest zmienne szczególnie musza sobie to wziąć do serca zespoły pracujące w metodologi AGILE. Powinniśmy więc zostawić przestrzeń na jej modyfikację.
VALUABLE
Musimy także wiedzieć jaka wartość biznesowa ma historyjka. Wszystkie historyjki powinny być połczone z jasno określonymi celami biznesowymi.
ESTIMABLE
Historyjka musi być na tyle zrozumiana przez zespół aby mógł określić ile czasu zajmie mu jego wykonanie. Nie oznacza to że powinniśmy już znać każdy szczegół implementacji.
SMALL
Historyjka musi być na tyle mała aby zmieścić się w jednym sprincie. Jednym z dobrych sposobów na podział to sprawdzenie gdzie w opisie występuje słowo lub oraz i, inne metody to:
  1.  Podział na podstawie kolejnych kroków użytkowania,
  2. Podział na podstaiwe I/O channel, każdy kanał może być oddzielna historia.
  3. Podzial ze wzgledu na dostepne opcje w funkcjonalności
  4. Podział ze względu na wykonywań roę, osobę
  5. Podział ze względu na datę. Każdy ważniejszy okres może być wykonany w oddzielnej historyjce,
  6. Podział ze względu na operacje CRUD.
Ważna uwaga. Nigdy dzielcie historyjek ze względu na system, komponent, szczegół architektury.
TESTABLE
Każda osoba zaangażowana w historyjkę musi się zgodzić w jaki sposób będzie ona testowana. Najlepiej aby każdy zespół miał zdefiniowane DoD (definition of done).
 
Przykładowe konwencje:

As ..  I want .. Then ..

 
As Product Owner
I want to see welcome screen while login for the web portal
Then I’m able to see my accounts
And I see my transactions
 

Given ..When .. Then 

Given I have already logged in to web portal on my computer
And I have never logged in to web portal on my mobile
When I log in web portal on my mobile
Then I can see log in screen

Jak zamknac proces na porcie

Poniżej przykładowa procedura jak usunac serwis, który nasłuchuje i blokuje port sieciowy.

1. Pobieramy aplikację CurrPorts , która wyświetla listę procesów aktualnie uruchomionych w systemie operacyjnym.

2. Odnajdujemy zablokowany port (kolumna Local Port)8080. W moim przypadku będzie to port 8080 zablokowany przez node.exe
3. Zapamiętujemy PID z kolumny Process Id

4. W konsoli Windows wpisujemy polecenie: taskkill /PID 1234 -F

Jeżeli proces został poprawnie zabity pownien w konsoli pojawić się komunikat:
SUCCESS: The process with PID <numer Process Id> has been terminated.

Interfejsy funkcjonalne wprowadzone w Java 8

Interfejs funkcjonalny jest interfejsem posiadającym przynajmniej jedną metodę abstrakcyjną (single abstract method). W omawianym interfejsie możesz zdefiniować wiele metod abstrakcyjnych i statycznych. Przykład Interfejsu funkcjonalnego:
java.util.function jest pakietem, który zawiera predefiniowane interfejsy.

4.1 Predicate 

Funkcja matematyczna, która zwraca wartość prawda fałsz. w zależności czy warunek zostanie spełniony lub nie. Czyli jest to metoda zwracająca wartość boolean.
– Predicate jest interfejsem funkcjonalnym wprowadzonym od Java 1.8
– interfejs zawiera tylko jedną metodę test(), która przyjmuje jedną wartość, wykonuje sprawdzenie na podstawie przesłanego warunku i  zwraca wartość boolean.

package functional.staticMethods;
import java.util.function.Predicate;

przykład implementacji interfejsu funkcjonalnego Predicate  przyjmującego parametr generyczny typu Integer

public class PredicateSampleInt {
  public static void main(String[] args) {
    Predicate<Integer> p = i -> i>10;
    System.out.println(p.test(100));
    System.out.println(p.test(9)); 

  }

inny przykład implementacji Predicate przyjmującego parametr generyczny typu String

public class PredicateSampleString {
  public static void main(String[] args) {
    Predicate<String> p = s -> s>5;
    System.out.println(p.test(„Ala ma kota));
    System.out.println(p.test(„Kot)); 
  }

inny przykład implementacji Predicate przyjmującego parametr generyczny typu Collection

public class PredicateSampleString {
  public static void main(String[] args) {
ArrayList a = new ArrayList<>{};
a.add(„a”);
    Predicate<Collection> p = c-> c.isEmpty();
    System.out.println(p.test(p(1));
    System.out.println(p.test(3)); 
  } 
istnieje również możliwość łączenia predykatów:
-negaca p1.negate()
-koniunkcja p1.and(p2)
-alternatywa p1.or(p2)

Różnice między interfejsem z metodą domyślną a klasą abstrakcyjną

Poniżej przedstawiam listę różnic pomiędzy interfejsem z metodą domyślną a klasą abstrakcyjną w Java 1.8

Interfejs z metodą domyślną:
1. Wewnątrz interfejsu każda zmienna jest zawsze public static final nie można zadeklarować instancji zmiennej.
2. Interfejs nie przechowuje stanu obiektu
3. Wewnątrz interfejsu nie można deklarować konstruktora
4. Wewnątrz interfejsu nie można deklarować instancji oraz bloków statycznych (static blocks)
5. Interfejs funkcjonalny z metodą domyślną może zawierać wyrażenia lambda
6. Wewnątrz interfejsu nie można nadpisywać metod klasy obiektowej (object class methods)

Klasa abstrakcyjna:
1. Wewnątrz klasy abstrakcyjnej można deklarować instancje zmiennych, które są wymagane w klasach dziedziczących.
2. Klasa abstrakcyjna może przechowywać stan obiektu
3. W klasie abstrakcyjnej można deklarować konstruktory
4. W klasie abstrakcyjnej można deklarować instancje obiektu oraz bloki statyczne
5. Klasa abstrakcyjna nie może zawierać wyrażeń lambda
6. Wewnątrz klasy abstrakcyjnej możesz nadpisywać metody klasy obiektowej

Nowe funkcje dodane w Java 8

Wersja 8 została wydana 18 marca 2014 roku. Wersja do pobrania JDK8.
Zasadnicze zmiany, które weszły wraz z Java 8:

  1. Wyrażenia lambda
  2. Interfejs funkcjonalny (functional interface)
  3. Domyślne i statyczne metody w interfejsach
  4. Interfejsy funkcjonalne dla:
    1. Predicate
    2. Function
    3. Consumer
    4. Supplier
  5. Referencje metod i konstruktorów (method reference, constructor reference) tworzone za przy użyciu operatora ” :: „
  6. Stream API
  7. Date and time API
W artykule szczegółowo opisuje każdy z nich.
in progress

1. Wyrażenia lambda

W Java jest to popularna nazwa dla funkcji anonimowej (Anonymous function) czyli takiej, która nie posiada nazwy, modyfikatora dostępu. Jest definiowana w klasie, która posiada dokładnie jedną instancję. 

Na początku zacznę od klasy anonimowej i przybliżę jej działanie. Następnie pokażę jak przejść z klasy anonimowej do funkcji anonimowej. Zarówno klasa jak i funkcja anonimowa są dla siebie równoważne i różnią się jedynie użytą składnią. Gdzie klasa anonimowa jest w rzeczywistości interfejsem funkcyjnym z dokładnie jedną abstrakcyjną metodą publiczną. A funkcja anonimowa to obiekt z dokładnie jedną metodą publiczną.
Klasy anonimowe zawsze są klasami wewnętrznymi.  Nie tworzymy klasy i nie korzystamy z jego konstruktora tak jak we wcześniejszych wersjach Java. Tworzymy za to instancję interfejsu new Predicate<Integer>(). Następnie dodajemy wszystkie metody implementowanego interfejsu. Dla interfejsu Predicate będzie to jedna metoda apply np. 
new Predicate<Integer>() { 
    public boolean apply(Integer integer) { 
        return (integer % 2) == 0; 
} };

Kolejnym krokiem jest przypisania nowo utworzonego predykatu do zmiennej np:

Predicate<Integer> isEven = new Predicate<Integer>() { 
    public boolean apply(Integer integer) { 
        return (integer % 2) == 0; 
} };

W momencie dodania predykatu do zmiennej, która jest wewnątrz metody będzie ona tworzona za każdym razem przy wywołaniu metody. Jeżeli chcemy to zoptymalizować i wywoływać predykat jeden raz przy ładowaniu klasy w pamięci. Możemy zadeklarować zmienną jako static i przenieść ją poza metodę.

Na koniec możemy użyć zmienną isEven w ten sposób:

Iterables.filter(data, isEven)

Jak przejść z klasy anonimowej do funkcji anonimowej?

W przypadku użycia IntelliJ program sam sugeruje ulepszenie kodu z stworzonej klasy anonimowej na funkcję anonimową (wyrażenia lambda):  
(o1, o2) -> { o1.compareTo(o2) }

Doszliśmy więc do tytułu pierwszego działu. Teraz przedstawię składnię wyrażenia lambda:

-> oddziela lewą część wyrażenia od prawej. Po lewej są zdefiniowane nazwy argumentów funkcji. Po prawej stronie jest ciało funkcji. Na prostym przykładzie funkcję w notacji matematycznej:
(x,y) → x² + y²
w Javie zapiszemy tak:
(x, y) -> x * x + y * y

Następnie powyższe wyrażenie lambda możemy uprościć pozbywając się niepotrzebnych elementów.

I tak w przypadku gdy jest po lewej stronie tylko jeden argument możemy nie pisać nawiasów:

x -> x * x
Gdy chcemy wykonać więcej operacji to dodajemy klamry do wyrażenia lambda:
(x, y) -> { 
    System.out.println(„Squaring ” + x + ” and ” + y);
    return x * x + y * y; 
}

W przypadku używania wyrażenia lambda nie musimy jawnie definiować typów argumentów funkcji. Możliwe jest to dzięki temu, że wyrażenia lambda można używać tylko w miejscach gdzie oczekiwania jest implementacja interfejsu funkcjonalnego. Na tej podstawie Java może wnioskować typy przyjmowane przez interfejs oraz wartości jakie zwróci.

Referencja do metody

 Funkcja anonimowa (integer) -> isEven.test(integer) jest równoznacza ze składnią isEven::test, gdzie isEven jest nazwą zmiennej, do której przypisana została metoda, którą chcemy wywołać.

List<Integer> data = new LinkedList<>(Arrays.asList(3, 1, 6, 2, 9, 0, 5, 4, 8, 7)); 
Predicate<Integer> isEven = (integer) -> integer % 2 == 0; 
System.out.println(Iterables.filter(data, isEven::test));

Na koniec można jeszcze zrezygnować z nazwy metody. Nasza nowo utworzona metoda jest w anonimowa:

List<Integer> data = new LinkedList<>(Arrays.asList(3, 1, 6, 2, 9, 0, 5, 4, 8, 7)); 
System.out.println(Iterables.filter(data, integer -> integer % 2 == 0));

2. Interfejs funkcjonalny (functional interface)

Przykładem zastosowania jest metoda forEach() 
Aktualnie gdy chcesz korzystać z kolekcji tworzysz Iterator, którego zadaniem jest przejście po wszystkich elementach kolekcji. Pracujesz więc na poziomie logiki biznesowej, jest to kod bardziej zrozumiały.

forEach() method in Iterable interface default and static methods in Interfaces Functional Interfaces and Lambda Expressions Java Stream API for Bulk Data Operations on Collections Java Time API Collection API improvements Concurrency API improvements Java IO improvements Miscellaneous Core API improvements

3. Domyślne i statyczne metody w interfejsach

Deklaracja interfejsu „SampleInterf” z zaimplementowaną metodą domyślną:

interface SampleInterf {
  default void main() {
    log.debug(„default method”);
  }
}


implementacja interfejsu:

class Test implements SampleInterf  {
  public static void main(String[] args) {
    Test t = new Test();
    t.main();
  }
}

Deklaracja interfejsu SampleInterfWithStaticMethod z metodą statyczną. Metodę tego typu możesz używać w praktyce jako klasę narzędziową w pakiecie (utility class). Takiej metody statycznej nie możesz również nadpisywać.

public interface SampleInterfWithStaticMethod {
  public static void m() {
    System.out.println(„interface with static method”);
  }
}


4. Interfejsy funkcjonalne

6. Stream API

Stream jest interfejsem z pakietu java.util.stream. Może przetwarzać każdy obiekt kolekcji (ArrayList, LinkedList, Vector, Stack, PriorityQueue, ArrayDeque, HashSet, LinkedHashSet, TreeSet). Tworzenie streamu wygląda następująco:
Stream s = c.stream();
Jeżeli mamy utworzony Stream możemy nad nim pracować w 2 krokach:

  1. Konfiguracja 
    1. Filtrowanie (.filter) w przypadku gdy chcemy wybrać interesujące nas pod elementy
    2. Mapowanie (.map) w przypadku gdy przetwarzamy elementy w Streamie (np. dodajemy)
  2. Przetwarzanie

src:

Angular 9 wydany

Dziś została wydana kolejna wersja Angulara. Jakie zmiany niesie ze sobą nowa wersja:

1. Ivy

Najważniejsza zmiana: Angular jest teraz domyślnie kompilowany z użyciem Ivy. Ivy czyli nowy silnik renderujący strony internetowe. Dzięki niemu paczki nowo stworzonych aplikacji mogą zajmować mniej miejsca na dysku. Dzięki czemu aplikacja będzie szybciej otwierała się w przeglądarce użytkownika.

2. Ahead-of-time

Przy uruchomieniu aplikacji za pomocą polecenia ng serve zostanie wykonana kompilacja ahead of time zamiast just in time. Może to za sobą nieść inne odświeżanie aplikacji w trakcie jej tworzenia.

3. Basic mode, full mode, strict mode

Możemy skonfigurować aplikację pod kątem sprawdzania nazw templatek. W jaki sposób ma się to odbywać. Funkcja ta była do tej pory dostępna jednak teraz jest jeszcze bardziej rozbudowana. Mamy do dyspozycji: basic mode, full mode, strict mode za ich pomocą można definiować w jaki sposób Angular ma parsować templatki komponentów.

4. @ViewChild(…{ static:false})  domyślnie

Użycie @ViewChild w celu wybrania elementu z templatki  powinno zawierać opcję static:true lub static:false   np w większości przypadków będzie to. @ViewChild(…{ static:false})  i taka wartość będzie przekazywana domyślnie jeżeli jej nie ustawimy i to jest zasadnicza różnica w Angularze 9. Nie trzeba  wartości static ustawiać w przypadku static:false. Jednak gdy chcemy użyć tego typu elementu np. w ngOnInit(). Czyli przed wykryciem zmian w kodzie. Powinna wartość @ViewChild być ustawiona na false

Instrukcja jak zaktualizować aplikację do najnowszej wersji Angulara: https://next.angular.io/guide/updating-to-version-9 . Są tam również przedstawione większe i mniejsze zmiany, które należy wziąć pod uwagę przy aktualizacji np. aktualnie wspierana wersja TypeScript to 3.6.

Aktualizacja za pomocą CLI:
npm install –no-save @angular/cli@^8.3.15
ng update @angular/cli @angular/core

src: https://blog.angular.io/version-9-of-angular-now-available-project-ivy-has-arrived-23c97b63cfa3