SlideShare a Scribd company logo
1 of 74
Angular 2+
Architektura aplikacji
Paweł Żurowski
Angular 2+
Dlaczego zwane też przydługim wstępem
Architektura aplikacji
Przykłady
Paweł Żurowski
Angular 2+
Dlaczego zwane też przydługim wstępem
Architektura aplikacji
Przykłady
Paweł Żurowski
Paradygmaty:
imperatywny vs deklaratywny
wykonywanie obliczeń w pętli
for vs forEach
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
// for
for (let i = 0; i < array.length; ++i) {
console.log(array[i]);
}
// forEach
array.forEach((item) => console.log(item));
for vs map
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
// for
const doubled1 = [];
for (let i = 0; i < array.length; ++i) {
let double = array[i] * 2;
doubled1.push(double);
}
// map
const doubled2 = array.map((item) => 2 * item);
for vs filter
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const isPrime = (n) => ...; // true or false
// for
const primes1 = [];
for (let i = 0; i < array.length; ++i) {
if(isPrime(array[i])){
primes1.push(array[i]);
}
}
// filter
const primes2 = array.filter(isPrime);
for vs reduce
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
// for
let sum1 = 0;
for (let i = 0; i < array.length; ++i) {
sum1 = sum1 + array[i];
}
// reduce
const sum2 = array.reduce((last, item) => last + item, 0);
for vs reduce
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const add = (a, b) => a + b;
// for
let sum1 = 0;
for (let i = 0; i < array.length; ++i) {
sum1 = add(sum1, array[i]);
}
// reduce
const sum2 = array.reduce(add, 0);
map-filter-reduce
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const double = (x) => 2 * x;
const isPrime = (n) => ...;
const add = (a, b) => a + b;
const doubled2 = array.map(double);
const primes2 = array.filter(isPrime);
const sum2 = array.reduce(add, 0);
map-filter-reduce
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const double = (x) => 2 * x;
const isPrime = (n) => ...;
const add = (a, b) => a + b;
const doubled2 = array.map(double);
const primes2 = array.filter(isPrime);
const sum2 = array.reduce(add, 0);
Skalar, tablica, promise, …
…trzy kropki
prymityw, tablica, promise, …
number
Array
<number>
Promise
<number>
?
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5){
return resolve('Success');
}else{
return reject('Failure')
}
}, 5 * 1000);
});
promise
.then((value) => console.log(value))
.catch((reason) => console.error(reason))
.finally(() => console.log('Done'));
prymityw, tablica, promise, …
number
Array
<number>
Promise
<number>
?
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
prymityw, tablica, promise, …
number
Array
<number>
Promise
<number>
?
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
prymityw, tablica, promise, …
number
Array
<number>
Promise
<number>
?
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
prymityw, tablica, promise, observable
number
Array
<number>
Promise
<number>
Observable
<number>
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
promise vs observable
promise
.then( (value) => console.log(value))
.catch( (reason) => console.error(reason))
.finally(() => console.log('Done'));
observable.subscribe(
(value) => console.log(value),
(reason) => console.error(reason),
() => console.log('Done')
);
promise vs observable
promise
.then( (value) => console.log(value))
;
observable.subscribe(
(value) => console.log(value)
);
promise vs observable
promise
.then((value) => console.log(value));
observable
.subscribe((value) => console.log(value));
promise vs observable
promise
.then((value) => console.log(value));
observable
.subscribe((value) => console.log(value));
prymityw, tablica, promise, observable
number
Iterable
<number>
Promise
<number>
Observable
<number>
jedna wartość wiele wartości
wartość dostępna teraz
wartość dostępna w przyszłości
pull semantics
push semantics
Observable - rxMarble
http://reactivex.io/assets/operators/legend.png
Operator debounce
Operator merge
Operator concat
map-filter-reduce --- przypomnienie
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const double = (x) => 2 * x;
const isPrime = (n) => ...;
const add = (a, b) => a + b;
const doubled2 = array.map(double);
const primes2 = array.filter(isPrime);
const sum2 = array.reduce(add, 0);
Operator map
Operator filter
Operator reduce
Operator scan
Wzorzec REDUX, ngrx
Stan…
• Stan (state) – wartości wszystkich zmiennych (np. komponentu,
aplikacji) w danym momencie, do których program ma dostęp.
…jest projektowany na…
Widok…
• Widok (view), GUI
• Widok funkcją stanu 𝑈𝐼 = 𝑓(𝑆𝑡𝑎𝑡𝑒)
…wywołuje…
Akcje…
• Akcja (action) – obiekt, który opisuje to, co się zdarzyło.
• Ważne – samo wyemitowanie akcji nie modyfikuje stanu.
…obsługiwane przez…
Reduktor…
• Reduktor (reducer) – czysta funkcja (pure function), która na
podstawie stanu i akcji synchronicznie (wręcz transakcyjnie) wylicza
nowy stan.
• Ważne – reduktor nie modyfikuje stanu – tworzy nowy stan.
• Ważne – reduktor nie wywołuje asynchronicznych funkcji.
…modyfikuje…
Store…
• Store – jeden obiekt, w którym zapisany jest stan całej aplikacji.
• Ważne – zapisany stan jest tylko do odczytu.
•  baza danych
…przechowuje…
Stan…
• Stan (state) – wartości wszystkich zmiennych (np. komponentu,
aplikacji) w danym momencie, do których program ma dostęp.
…jest projektowany na… itd.
Wzorzec REDUX
Store
State
ViewActions
Reducer
przechowuje
jest projektowany na
wywołuje
obsługiwane przez
modyfikuje
https://medium.com/@flashMasterJim/setting-up-ngrx-store-in-an-angular-2-project-e5232a7b082e#.23yso3phj
Dlaczego reduktor?
interface ActionReducer<T> {
(state: T, action: Action): T;
}
const dumbReducer = (state, action) => state;
Reduktor z przykładowej aplikacji
export function reducer(state = initialState, action: ActionType): State {
switch (action.type) {
case Types.ADD:
case Types.REMOVE:
case Types.QUERY:
case Types.UPDATE:
return Object.assign({}, state, {loading: true});
case Types.ADDED:
return Object.assign({}, state, {loading: false}, {greetings: [...state.greetings, action.payload]});
case Types.REMOVED:
return Object.assign({}, state, {loading: false}, {greetings: state.greetings.filter(({id}) => id !== action.payload.id)});
case Types.UPDATED:
return Object.assign({}, state, {loading: false},
{greetings: state.greetings.map((gr) => gr.id === action.payload.id ? action.payload : gr)});
case Types.QUERIED:
return Object.assign({}, state, {loading: false}, {greetings: action.payload});
case Types.SORT:
return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)});
case Types.RSORT:
return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))});
default:
return state;
}
}
function reducer(state = initialState, action: ActionType): State {
switch (action.type) {
// ...
case Types.SORT:
return Object.assign({}, state,
{greetings: sort(state.greetings, valueComparator)});
case Types.RSORT:
return Object.assign({}, state,
{greetings: sort(state.greetings, (a, b) => valueComparator(b, a))});
default:
return state;
}
}
function reducer(state = initialState, action: ActionType): State {
switch (action.type) {
// ...
case Types.SORT:
return Object.assign({}, state,
{greetings: sort(state.greetings, valueComparator)});
case Types.RSORT:
return Object.assign({}, state,
{greetings: sort(state.greetings, (a, b) => valueComparator(b, a))});
default:
return state;
}
}
Reduktor z przykładowej aplikacji
export function reducer(state = initialState, action: ActionType): State {
switch (action.type) {
case Types.ADD:
case Types.REMOVE:
case Types.QUERY:
case Types.UPDATE:
return Object.assign({}, state, {loading: true});
case Types.ADDED:
return Object.assign({}, state, {loading: false}, {greetings: [...state.greetings, action.payload]});
case Types.REMOVED:
return Object.assign({}, state, {loading: false}, {greetings: state.greetings.filter(({id}) => id !== action.payload.id)});
case Types.UPDATED:
return Object.assign({}, state, {loading: false},
{greetings: state.greetings.map((gr) => gr.id === action.payload.id ? action.payload : gr)});
case Types.QUERIED:
return Object.assign({}, state, {loading: false}, {greetings: action.payload});
case Types.SORT:
return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)});
case Types.RSORT:
return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))});
default:
return state;
}
}
Operator scan – przypomnienie
ngrx/Store
• Po każdej akcji zostanie wypchnięty nowy stan
• Wszystko, co zasubskrybowało store, dostanie odpowiedni jego
fragment, o ile…
• …w ogóle się zmienił (a korzystamy z niemutowalnego drzewa stanu)
Nowy stan
Panel
Nagłówek
Ikona Tekst
Treść
Lorem
Ipsum
Panel
Nagłówek
Ikona Tekst
Treść
Ala ma
kota
Modyfikacja tekstu
Kopia referencji
Asynchroniczne wywołania – ngrx/Effects
• Wywoływane „obok”
• Nasłuchują akcji
• Gdy odpowiednia nadejdzie – wywołują asynchroniczny kod
(np. http)
• Po zakończeniu – zwracają 0..* akcji
• To także observables (można korzystać z operatorów, np.
debounce czy switchMap)
• switchMap w połączeniu z http potrafi anulować request –
out of the box
Architektura aplikacji
@ngrx/Store
Service
Smart Comp.
Dumb Comp.
Reducers
@ngrx/Effects
Effects Service
Data Service
HTTP
new state
select state (observable)
state (observable)
properties (bind)events
call
action (dispatch)
state + action
action (dispatch)
state + action
state + action
state (call)
state (call)response (observable)
response (observable)
state + action
https://youtu.be/pjwVq8B-ZAw w 21:55 i w 33:45
Wzorzec REDUX - dodatkowe korzyści
• Transakcyjne modyfikowanie stanu aplikacji
• Separacja logiki od prezentacji
• Możliwość zapisania stanu aplikacji w każdym momencie
• Możliwość odtworzenia wyglądu aplikacji z zapisanego stanu
(widok funkcją stanu)
• Time-travel debug – oprócz stanu można zapisać n (być może
nawet duże N) ostatnich akcji – możliwość odtworzenia
przebiegu działań użytkownika
• Dirty checking – niepotrzebne
Angular (2+) building blocks
Typescript/ES2015, templates, examples
Typescript: typy
function asd() {
var a = 42;
var b = 'hello';
b = a; // Type 'number' is not assignable to type 'string'
return b;
}
console.log(asd()); // 42
var x: number;
ES2015: let, const
function x() {
var V = 1;
let L = 1;
const C = 1;
if (this) {
var V = 2;
let L = 2;
C = 4; // Cannot assign to 'C' because it is
// a constant or a read-only property.
}
console.log(L, V, C); // 1 2 4
}
Typescript: interfejsy
interface Action {
type: string; payload?: any;
}
interface ActionReducer<T> {
(state: T, action: Action): T;
}
let typeCache: { [label: string]: boolean } = {};
function sort<T>(
array: Array<T>,
compareFn?: (a: T, b: T) => number): Array<T> {
const shallowCopy = array.map(i => i);
shallowCopy.sort(compareFn); return shallowCopy;
}
ES2015: fat arrow function (fart)
function MyObject() {
this.value = 42;
}
MyObject.prototype.method = function method() {
setTimeout(() => console.log(this.value));
};
ES2015: template literals
const a = 10;
const b = 30;
const c = 24;
const template = `
${a} + ${b} = ${a + b}
${a} * ${c} = ${a * c}
max(a,b,c) = ${Math.max(a, b, c)}
min(b,c) = ${Math.min(b, c)}
`;
ES2015: spread rest
const a = [1,2,3];
const b = [10, 20, 30];
// spread operator
const c = [...a, -1, ...b];
// rest operator
const f = (n: number, ...x) => n * x.length;
ES2015: destructuring
interface PersonalData {
firstName: string,
lastName: string,
age: number,
address: {city: string, postalCode: string}
}
function fullName({firstName, lastName}: PersonalData) {
return `${firstName} ${lastName}`;
}
function simpleRecord({firstName, address}: PersonalData) {
const {city} = address;
return {firstName, city};
}
ES2015: default parameters
function createSth(name = 'defaultName') {
//...
}
const validateCar = ({engine, suspension} = DUMMY_CAR)
=> engine && suspension;
ES2015: import export
// sort.ts
export function sort<T>(array: Array<T>,
compareFn?: (a: T, b: T) => number): Array<T> {
const shallowCopy = array.map(i => i);
shallowCopy.sort(compareFn);
return shallowCopy;
}
// somewhere.ts
import {sort} from './sort';
declare function doProcess(array: Array<number>);
declare function takeArray(): Array<number>;
doProcess(sort(takeArray()));
ES5: obiekty z prototypem
function Something
( value) {
this.initialized = true;
this.value = value;
}
Something.prototype.somewhere = function somewhere(n) {
this.somehow = this.value + n;
};
var thing = new Something(42);
thing.somewhere(2);
console.log(thing.somehow());
ES2015: klasy (ale nie „klasyczne”!)
class Something {
constructor(public value) {
this.initialized = true;
}
somewhere(n) {
this.somehow = this.value + n;
};
}
var thing = new Something(42);
thing.somewhere(2);
console.log(thing.somehow());
ES2015: klasy (ale nie „klasyczne”!)
class Something {
constructor(public value) {
this.initialized = true;
}
somewhere(n) {
this.somehow = this.value + n;
};
}
var thing = new Something(42);
thing.somewhere(2);
console.log(thing.somehow());
Typescript: decorators
const dog = (language) => function (target) {
target.prototype.speak = () =>
language === 'pl' ? 'hau!' : 'woof!'
};
interface Speakable { speak(what: string): string; }
@dog('pl')
class Animal implements Speakable {
speak() { return 'speaking'; }
}
const s = new Animal();
console.log(s.speak());
Angular 2+: szablony
• {{interpolation}}
• [propertyBinding]
• (eventBindging)
• *structure
• #ref
<span>{{ firstName }}</span>
<img [src]="i.src" alt="image"/>
<a (click)="doIt()">do</a>
<div *ngIf="isVisible">sth</div>
Przykłady w kodzie
• Reducer
• Reducer – testy
• Effects
• Effects – testy
• Service
• Service –testy
• Component (smart, dumb)
• Component – testy
Podsumowanie
Deklaratywnie, Observable, Redux, Architektura
map-filter-reduce
const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
const double = (x) => 2 * x;
const isPrime = (n) => ...;
const add = (a, b) => a + b;
const doubled2 = array.map(double);
const primes2 = array.filter(isPrime);
const sum2 = array.reduce(add, 0);
Observable - rxMarble
http://reactivex.io/assets/operators/legend.png
Wzorzec REDUX
Store
State
ViewActions
Reducer
przechowuje
jest projektowany na
wywołuje
obsługiwane przez
modyfikuje
https://medium.com/@flashMasterJim/setting-up-ngrx-store-in-an-angular-2-project-e5232a7b082e#.23yso3phj
Architektura aplikacji
@ngrx/Store
Service
Smart Comp.
Dumb Comp.
Reducers
@ngrx/Effects
Effects Service
Data Service
HTTP
new state
select state (observable)
state (observable)
properties (bind)events
call
action (dispatch)
state + action
action (dispatch)
state + action
state + action
state (call)
state (call)response (observable)
response (observable)
state + action
https://youtu.be/pjwVq8B-ZAw w 21:55 i w 33:45
Wypadałoby jeszcze wspomnieć o:
• Narzędziach: Redux Dev Tools, Augury
• Style guide: https://angular.io/docs/ts/latest/guide/style-guide.html
• Reactive forms, reactive router, ngrx/router
• Testach jednostkowych:
• jednostka != plik, jednostka != klasa, jednostka != serwis
• AAA – arrange, act, assert
• https://angular.io/docs/ts/latest/guide/testing.html - guide
• https://docs.google.com/presentation/d/1gJCBr_M5dCcCX9WUM52ZUAKVlPj
6hQv3MYXKlgFMpSA/edit?usp=sharing - przykłady
• Korzystając z tej architektury celowo rezygnuje się części
funkcjonalności oferowanych przez Typescript i Angular
Koniec.

More Related Content

What's hot

Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...The Software House
 
Analizy Przestrzenne z wykorzystaniem GRASS vol.15
Analizy Przestrzenne z wykorzystaniem GRASS vol.15Analizy Przestrzenne z wykorzystaniem GRASS vol.15
Analizy Przestrzenne z wykorzystaniem GRASS vol.15WGUG
 
Wprowadzenie do Reactive Extensions (RX) dla .NET
Wprowadzenie do Reactive Extensions (RX) dla .NETWprowadzenie do Reactive Extensions (RX) dla .NET
Wprowadzenie do Reactive Extensions (RX) dla .NETMaciej Zbrzezny
 

What's hot (8)

Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
 
Podstawy php
Podstawy phpPodstawy php
Podstawy php
 
Podstawy php
Podstawy phpPodstawy php
Podstawy php
 
Analizy Przestrzenne z wykorzystaniem GRASS vol.15
Analizy Przestrzenne z wykorzystaniem GRASS vol.15Analizy Przestrzenne z wykorzystaniem GRASS vol.15
Analizy Przestrzenne z wykorzystaniem GRASS vol.15
 
Wprowadzenie do Reactive Extensions (RX) dla .NET
Wprowadzenie do Reactive Extensions (RX) dla .NETWprowadzenie do Reactive Extensions (RX) dla .NET
Wprowadzenie do Reactive Extensions (RX) dla .NET
 
Angular Restmod
Angular RestmodAngular Restmod
Angular Restmod
 
Prezentacja php3
Prezentacja   php3Prezentacja   php3
Prezentacja php3
 
Php P.Jar
Php P.JarPhp P.Jar
Php P.Jar
 

Viewers also liked

Quick introduction to Angular 4 for AngularJS 1.5 developers
Quick introduction to Angular 4 for AngularJS 1.5 developersQuick introduction to Angular 4 for AngularJS 1.5 developers
Quick introduction to Angular 4 for AngularJS 1.5 developersPaweł Żurowski
 
REKRUTACJA DWUJĘZYCZNE GIMNAZJUM
REKRUTACJA DWUJĘZYCZNE GIMNAZJUMREKRUTACJA DWUJĘZYCZNE GIMNAZJUM
REKRUTACJA DWUJĘZYCZNE GIMNAZJUMEdukacja_Spoleczna
 
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie IIPHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie IIWydawnictwo Helion
 
Wady orzeczeń sądowych w postępowaniu cywilnym - ebook
Wady orzeczeń sądowych w postępowaniu cywilnym - ebookWady orzeczeń sądowych w postępowaniu cywilnym - ebook
Wady orzeczeń sądowych w postępowaniu cywilnym - ebooke-booksweb.pl
 
Prezentacja działań marketingowych Miasta Poznania w 2013 r.
Prezentacja działań marketingowych Miasta Poznania w 2013 r.Prezentacja działań marketingowych Miasta Poznania w 2013 r.
Prezentacja działań marketingowych Miasta Poznania w 2013 r.City of Poznan
 
Jak zarządzac sobą w czasie?
Jak zarządzac sobą w czasie?Jak zarządzac sobą w czasie?
Jak zarządzac sobą w czasie?Zielona Linia
 
Oracle SQL Performance Tuning and Optimization v26 chapter 1
Oracle SQL Performance Tuning and Optimization v26 chapter 1Oracle SQL Performance Tuning and Optimization v26 chapter 1
Oracle SQL Performance Tuning and Optimization v26 chapter 1Kevin Meade
 
Oracle Performance Tuning Fundamentals
Oracle Performance Tuning FundamentalsOracle Performance Tuning Fundamentals
Oracle Performance Tuning FundamentalsCarlos Sierra
 
Technik.hotelarstwa 341[04] z5.01_u
Technik.hotelarstwa 341[04] z5.01_uTechnik.hotelarstwa 341[04] z5.01_u
Technik.hotelarstwa 341[04] z5.01_uPusiu99
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsRan Mizrahi
 
Introduction to Angular 2
Introduction to Angular 2Introduction to Angular 2
Introduction to Angular 2Knoldus Inc.
 
Getting Started with Angular 2
Getting Started with Angular 2Getting Started with Angular 2
Getting Started with Angular 2FITC
 
Understanding DB2 Optimizer
Understanding DB2 OptimizerUnderstanding DB2 Optimizer
Understanding DB2 Optimizerterraborealis
 
Oracle Sql Tuning
Oracle Sql TuningOracle Sql Tuning
Oracle Sql TuningChris Adkin
 

Viewers also liked (18)

Quick introduction to Angular 4 for AngularJS 1.5 developers
Quick introduction to Angular 4 for AngularJS 1.5 developersQuick introduction to Angular 4 for AngularJS 1.5 developers
Quick introduction to Angular 4 for AngularJS 1.5 developers
 
Mistrzologia
MistrzologiaMistrzologia
Mistrzologia
 
REKRUTACJA DWUJĘZYCZNE GIMNAZJUM
REKRUTACJA DWUJĘZYCZNE GIMNAZJUMREKRUTACJA DWUJĘZYCZNE GIMNAZJUM
REKRUTACJA DWUJĘZYCZNE GIMNAZJUM
 
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie IIPHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
 
Wady orzeczeń sądowych w postępowaniu cywilnym - ebook
Wady orzeczeń sądowych w postępowaniu cywilnym - ebookWady orzeczeń sądowych w postępowaniu cywilnym - ebook
Wady orzeczeń sądowych w postępowaniu cywilnym - ebook
 
Organized Crime In Poland
Organized Crime In PolandOrganized Crime In Poland
Organized Crime In Poland
 
Prezentacja działań marketingowych Miasta Poznania w 2013 r.
Prezentacja działań marketingowych Miasta Poznania w 2013 r.Prezentacja działań marketingowych Miasta Poznania w 2013 r.
Prezentacja działań marketingowych Miasta Poznania w 2013 r.
 
Jak zarządzac sobą w czasie?
Jak zarządzac sobą w czasie?Jak zarządzac sobą w czasie?
Jak zarządzac sobą w czasie?
 
Ustawa o pdop
Ustawa o pdopUstawa o pdop
Ustawa o pdop
 
React 101
React 101React 101
React 101
 
Oracle SQL Performance Tuning and Optimization v26 chapter 1
Oracle SQL Performance Tuning and Optimization v26 chapter 1Oracle SQL Performance Tuning and Optimization v26 chapter 1
Oracle SQL Performance Tuning and Optimization v26 chapter 1
 
Oracle Performance Tuning Fundamentals
Oracle Performance Tuning FundamentalsOracle Performance Tuning Fundamentals
Oracle Performance Tuning Fundamentals
 
Technik.hotelarstwa 341[04] z5.01_u
Technik.hotelarstwa 341[04] z5.01_uTechnik.hotelarstwa 341[04] z5.01_u
Technik.hotelarstwa 341[04] z5.01_u
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design Patterns
 
Introduction to Angular 2
Introduction to Angular 2Introduction to Angular 2
Introduction to Angular 2
 
Getting Started with Angular 2
Getting Started with Angular 2Getting Started with Angular 2
Getting Started with Angular 2
 
Understanding DB2 Optimizer
Understanding DB2 OptimizerUnderstanding DB2 Optimizer
Understanding DB2 Optimizer
 
Oracle Sql Tuning
Oracle Sql TuningOracle Sql Tuning
Oracle Sql Tuning
 

Similar to Architektura ngrx w angular 2+

React Ninja - Warsztaty TDD + React + Redux + Websockets
React Ninja - Warsztaty TDD + React + Redux + WebsocketsReact Ninja - Warsztaty TDD + React + Redux + Websockets
React Ninja - Warsztaty TDD + React + Redux + WebsocketsThe Software House
 
Confitura 2018 - Sekretne życie jobów Sparkowych
Confitura 2018 - Sekretne życie jobów SparkowychConfitura 2018 - Sekretne życie jobów Sparkowych
Confitura 2018 - Sekretne życie jobów SparkowychMarcin Jasiński
 
ASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaBartlomiej Zass
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxDawid Rusnak
 
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016PROIDEA
 
TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPPiotr Gabryjeluk
 
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"Dariusz Kalbarczyk
 
Drzewa przedziałowe
Drzewa przedziałoweDrzewa przedziałowe
Drzewa przedziałoweMejczus
 
DreamLab Academy #12 Wprowadzenie do React.js
DreamLab Academy #12 Wprowadzenie do React.jsDreamLab Academy #12 Wprowadzenie do React.js
DreamLab Academy #12 Wprowadzenie do React.jsDreamLab
 
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...Trójmiejska Grupa Testerska
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?The Software House
 
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...PROIDEA
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawyApptension
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariowaćJakub Marchwicki
 
Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011Rafal Piekarski
 
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...PROIDEA
 
Łagodne wprowadzenie do Angular2
Łagodne wprowadzenie do Angular2Łagodne wprowadzenie do Angular2
Łagodne wprowadzenie do Angular2Jakub Nietrzeba
 
Angular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIAngular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIThe Software House
 
Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Andrzej Krzywda
 

Similar to Architektura ngrx w angular 2+ (20)

React Ninja - Warsztaty TDD + React + Redux + Websockets
React Ninja - Warsztaty TDD + React + Redux + WebsocketsReact Ninja - Warsztaty TDD + React + Redux + Websockets
React Ninja - Warsztaty TDD + React + Redux + Websockets
 
Confitura 2018 - Sekretne życie jobów Sparkowych
Confitura 2018 - Sekretne życie jobów SparkowychConfitura 2018 - Sekretne życie jobów Sparkowych
Confitura 2018 - Sekretne życie jobów Sparkowych
 
ASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założenia
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/Redux
 
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
 
TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHP
 
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"
AngularJS Warsaw #4 - Dariusz Kalbarczyk "Controller as"
 
Drzewa przedziałowe
Drzewa przedziałoweDrzewa przedziałowe
Drzewa przedziałowe
 
DreamLab Academy #12 Wprowadzenie do React.js
DreamLab Academy #12 Wprowadzenie do React.jsDreamLab Academy #12 Wprowadzenie do React.js
DreamLab Academy #12 Wprowadzenie do React.js
 
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...
TGT#11 - Zostały Ci jeszcze jakieś włosy? (Testowanie programów równoległych)...
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
 
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...
4Developers 2015: Orleans - aplikacje, które skalują i dystrybuują się same -...
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawy
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować
 
Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011
 
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...
4Developers 2015: Przejrzysty i testowalny kod na Androidzie? Spróbujmy z Cle...
 
Łagodne wprowadzenie do Angular2
Łagodne wprowadzenie do Angular2Łagodne wprowadzenie do Angular2
Łagodne wprowadzenie do Angular2
 
Angular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIAngular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z API
 
Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]Single Page Applications with CoffeeScript [Polish]
Single Page Applications with CoffeeScript [Polish]
 
Platforma Kontentowa
Platforma KontentowaPlatforma Kontentowa
Platforma Kontentowa
 

Architektura ngrx w angular 2+

  • 2. Angular 2+ Dlaczego zwane też przydługim wstępem Architektura aplikacji Przykłady Paweł Żurowski
  • 3. Angular 2+ Dlaczego zwane też przydługim wstępem Architektura aplikacji Przykłady Paweł Żurowski
  • 5. for vs forEach const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; // for for (let i = 0; i < array.length; ++i) { console.log(array[i]); } // forEach array.forEach((item) => console.log(item));
  • 6. for vs map const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; // for const doubled1 = []; for (let i = 0; i < array.length; ++i) { let double = array[i] * 2; doubled1.push(double); } // map const doubled2 = array.map((item) => 2 * item);
  • 7. for vs filter const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const isPrime = (n) => ...; // true or false // for const primes1 = []; for (let i = 0; i < array.length; ++i) { if(isPrime(array[i])){ primes1.push(array[i]); } } // filter const primes2 = array.filter(isPrime);
  • 8. for vs reduce const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; // for let sum1 = 0; for (let i = 0; i < array.length; ++i) { sum1 = sum1 + array[i]; } // reduce const sum2 = array.reduce((last, item) => last + item, 0);
  • 9. for vs reduce const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const add = (a, b) => a + b; // for let sum1 = 0; for (let i = 0; i < array.length; ++i) { sum1 = add(sum1, array[i]); } // reduce const sum2 = array.reduce(add, 0);
  • 10. map-filter-reduce const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const double = (x) => 2 * x; const isPrime = (n) => ...; const add = (a, b) => a + b; const doubled2 = array.map(double); const primes2 = array.filter(isPrime); const sum2 = array.reduce(add, 0);
  • 11. map-filter-reduce const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const double = (x) => 2 * x; const isPrime = (n) => ...; const add = (a, b) => a + b; const doubled2 = array.map(double); const primes2 = array.filter(isPrime); const sum2 = array.reduce(add, 0);
  • 12. Skalar, tablica, promise, … …trzy kropki
  • 13. prymityw, tablica, promise, … number Array <number> Promise <number> ? jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości
  • 14. Promise const promise = new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() < 0.5){ return resolve('Success'); }else{ return reject('Failure') } }, 5 * 1000); }); promise .then((value) => console.log(value)) .catch((reason) => console.error(reason)) .finally(() => console.log('Done'));
  • 15. prymityw, tablica, promise, … number Array <number> Promise <number> ? jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości
  • 16. prymityw, tablica, promise, … number Array <number> Promise <number> ? jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości
  • 17. prymityw, tablica, promise, … number Array <number> Promise <number> ? jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości
  • 18. prymityw, tablica, promise, observable number Array <number> Promise <number> Observable <number> jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości
  • 19. promise vs observable promise .then( (value) => console.log(value)) .catch( (reason) => console.error(reason)) .finally(() => console.log('Done')); observable.subscribe( (value) => console.log(value), (reason) => console.error(reason), () => console.log('Done') );
  • 20. promise vs observable promise .then( (value) => console.log(value)) ; observable.subscribe( (value) => console.log(value) );
  • 21. promise vs observable promise .then((value) => console.log(value)); observable .subscribe((value) => console.log(value));
  • 22. promise vs observable promise .then((value) => console.log(value)); observable .subscribe((value) => console.log(value));
  • 23. prymityw, tablica, promise, observable number Iterable <number> Promise <number> Observable <number> jedna wartość wiele wartości wartość dostępna teraz wartość dostępna w przyszłości pull semantics push semantics
  • 28. map-filter-reduce --- przypomnienie const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const double = (x) => 2 * x; const isPrime = (n) => ...; const add = (a, b) => a + b; const doubled2 = array.map(double); const primes2 = array.filter(isPrime); const sum2 = array.reduce(add, 0);
  • 34. Stan… • Stan (state) – wartości wszystkich zmiennych (np. komponentu, aplikacji) w danym momencie, do których program ma dostęp. …jest projektowany na…
  • 35. Widok… • Widok (view), GUI • Widok funkcją stanu 𝑈𝐼 = 𝑓(𝑆𝑡𝑎𝑡𝑒) …wywołuje…
  • 36. Akcje… • Akcja (action) – obiekt, który opisuje to, co się zdarzyło. • Ważne – samo wyemitowanie akcji nie modyfikuje stanu. …obsługiwane przez…
  • 37. Reduktor… • Reduktor (reducer) – czysta funkcja (pure function), która na podstawie stanu i akcji synchronicznie (wręcz transakcyjnie) wylicza nowy stan. • Ważne – reduktor nie modyfikuje stanu – tworzy nowy stan. • Ważne – reduktor nie wywołuje asynchronicznych funkcji. …modyfikuje…
  • 38. Store… • Store – jeden obiekt, w którym zapisany jest stan całej aplikacji. • Ważne – zapisany stan jest tylko do odczytu. •  baza danych …przechowuje…
  • 39. Stan… • Stan (state) – wartości wszystkich zmiennych (np. komponentu, aplikacji) w danym momencie, do których program ma dostęp. …jest projektowany na… itd.
  • 40. Wzorzec REDUX Store State ViewActions Reducer przechowuje jest projektowany na wywołuje obsługiwane przez modyfikuje https://medium.com/@flashMasterJim/setting-up-ngrx-store-in-an-angular-2-project-e5232a7b082e#.23yso3phj
  • 41. Dlaczego reduktor? interface ActionReducer<T> { (state: T, action: Action): T; } const dumbReducer = (state, action) => state;
  • 42. Reduktor z przykładowej aplikacji export function reducer(state = initialState, action: ActionType): State { switch (action.type) { case Types.ADD: case Types.REMOVE: case Types.QUERY: case Types.UPDATE: return Object.assign({}, state, {loading: true}); case Types.ADDED: return Object.assign({}, state, {loading: false}, {greetings: [...state.greetings, action.payload]}); case Types.REMOVED: return Object.assign({}, state, {loading: false}, {greetings: state.greetings.filter(({id}) => id !== action.payload.id)}); case Types.UPDATED: return Object.assign({}, state, {loading: false}, {greetings: state.greetings.map((gr) => gr.id === action.payload.id ? action.payload : gr)}); case Types.QUERIED: return Object.assign({}, state, {loading: false}, {greetings: action.payload}); case Types.SORT: return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)}); case Types.RSORT: return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))}); default: return state; } }
  • 43. function reducer(state = initialState, action: ActionType): State { switch (action.type) { // ... case Types.SORT: return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)}); case Types.RSORT: return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))}); default: return state; } }
  • 44. function reducer(state = initialState, action: ActionType): State { switch (action.type) { // ... case Types.SORT: return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)}); case Types.RSORT: return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))}); default: return state; } }
  • 45. Reduktor z przykładowej aplikacji export function reducer(state = initialState, action: ActionType): State { switch (action.type) { case Types.ADD: case Types.REMOVE: case Types.QUERY: case Types.UPDATE: return Object.assign({}, state, {loading: true}); case Types.ADDED: return Object.assign({}, state, {loading: false}, {greetings: [...state.greetings, action.payload]}); case Types.REMOVED: return Object.assign({}, state, {loading: false}, {greetings: state.greetings.filter(({id}) => id !== action.payload.id)}); case Types.UPDATED: return Object.assign({}, state, {loading: false}, {greetings: state.greetings.map((gr) => gr.id === action.payload.id ? action.payload : gr)}); case Types.QUERIED: return Object.assign({}, state, {loading: false}, {greetings: action.payload}); case Types.SORT: return Object.assign({}, state, {greetings: sort(state.greetings, valueComparator)}); case Types.RSORT: return Object.assign({}, state, {greetings: sort(state.greetings, (a, b) => valueComparator(b, a))}); default: return state; } }
  • 46. Operator scan – przypomnienie
  • 47. ngrx/Store • Po każdej akcji zostanie wypchnięty nowy stan • Wszystko, co zasubskrybowało store, dostanie odpowiedni jego fragment, o ile… • …w ogóle się zmienił (a korzystamy z niemutowalnego drzewa stanu)
  • 48. Nowy stan Panel Nagłówek Ikona Tekst Treść Lorem Ipsum Panel Nagłówek Ikona Tekst Treść Ala ma kota Modyfikacja tekstu Kopia referencji
  • 49. Asynchroniczne wywołania – ngrx/Effects • Wywoływane „obok” • Nasłuchują akcji • Gdy odpowiednia nadejdzie – wywołują asynchroniczny kod (np. http) • Po zakończeniu – zwracają 0..* akcji • To także observables (można korzystać z operatorów, np. debounce czy switchMap) • switchMap w połączeniu z http potrafi anulować request – out of the box
  • 50. Architektura aplikacji @ngrx/Store Service Smart Comp. Dumb Comp. Reducers @ngrx/Effects Effects Service Data Service HTTP new state select state (observable) state (observable) properties (bind)events call action (dispatch) state + action action (dispatch) state + action state + action state (call) state (call)response (observable) response (observable) state + action https://youtu.be/pjwVq8B-ZAw w 21:55 i w 33:45
  • 51. Wzorzec REDUX - dodatkowe korzyści • Transakcyjne modyfikowanie stanu aplikacji • Separacja logiki od prezentacji • Możliwość zapisania stanu aplikacji w każdym momencie • Możliwość odtworzenia wyglądu aplikacji z zapisanego stanu (widok funkcją stanu) • Time-travel debug – oprócz stanu można zapisać n (być może nawet duże N) ostatnich akcji – możliwość odtworzenia przebiegu działań użytkownika • Dirty checking – niepotrzebne
  • 52. Angular (2+) building blocks Typescript/ES2015, templates, examples
  • 53. Typescript: typy function asd() { var a = 42; var b = 'hello'; b = a; // Type 'number' is not assignable to type 'string' return b; } console.log(asd()); // 42 var x: number;
  • 54. ES2015: let, const function x() { var V = 1; let L = 1; const C = 1; if (this) { var V = 2; let L = 2; C = 4; // Cannot assign to 'C' because it is // a constant or a read-only property. } console.log(L, V, C); // 1 2 4 }
  • 55. Typescript: interfejsy interface Action { type: string; payload?: any; } interface ActionReducer<T> { (state: T, action: Action): T; } let typeCache: { [label: string]: boolean } = {}; function sort<T>( array: Array<T>, compareFn?: (a: T, b: T) => number): Array<T> { const shallowCopy = array.map(i => i); shallowCopy.sort(compareFn); return shallowCopy; }
  • 56. ES2015: fat arrow function (fart) function MyObject() { this.value = 42; } MyObject.prototype.method = function method() { setTimeout(() => console.log(this.value)); };
  • 57. ES2015: template literals const a = 10; const b = 30; const c = 24; const template = ` ${a} + ${b} = ${a + b} ${a} * ${c} = ${a * c} max(a,b,c) = ${Math.max(a, b, c)} min(b,c) = ${Math.min(b, c)} `;
  • 58. ES2015: spread rest const a = [1,2,3]; const b = [10, 20, 30]; // spread operator const c = [...a, -1, ...b]; // rest operator const f = (n: number, ...x) => n * x.length;
  • 59. ES2015: destructuring interface PersonalData { firstName: string, lastName: string, age: number, address: {city: string, postalCode: string} } function fullName({firstName, lastName}: PersonalData) { return `${firstName} ${lastName}`; } function simpleRecord({firstName, address}: PersonalData) { const {city} = address; return {firstName, city}; }
  • 60. ES2015: default parameters function createSth(name = 'defaultName') { //... } const validateCar = ({engine, suspension} = DUMMY_CAR) => engine && suspension;
  • 61. ES2015: import export // sort.ts export function sort<T>(array: Array<T>, compareFn?: (a: T, b: T) => number): Array<T> { const shallowCopy = array.map(i => i); shallowCopy.sort(compareFn); return shallowCopy; } // somewhere.ts import {sort} from './sort'; declare function doProcess(array: Array<number>); declare function takeArray(): Array<number>; doProcess(sort(takeArray()));
  • 62. ES5: obiekty z prototypem function Something ( value) { this.initialized = true; this.value = value; } Something.prototype.somewhere = function somewhere(n) { this.somehow = this.value + n; }; var thing = new Something(42); thing.somewhere(2); console.log(thing.somehow());
  • 63. ES2015: klasy (ale nie „klasyczne”!) class Something { constructor(public value) { this.initialized = true; } somewhere(n) { this.somehow = this.value + n; }; } var thing = new Something(42); thing.somewhere(2); console.log(thing.somehow());
  • 64. ES2015: klasy (ale nie „klasyczne”!) class Something { constructor(public value) { this.initialized = true; } somewhere(n) { this.somehow = this.value + n; }; } var thing = new Something(42); thing.somewhere(2); console.log(thing.somehow());
  • 65. Typescript: decorators const dog = (language) => function (target) { target.prototype.speak = () => language === 'pl' ? 'hau!' : 'woof!' }; interface Speakable { speak(what: string): string; } @dog('pl') class Animal implements Speakable { speak() { return 'speaking'; } } const s = new Animal(); console.log(s.speak());
  • 66. Angular 2+: szablony • {{interpolation}} • [propertyBinding] • (eventBindging) • *structure • #ref <span>{{ firstName }}</span> <img [src]="i.src" alt="image"/> <a (click)="doIt()">do</a> <div *ngIf="isVisible">sth</div>
  • 67. Przykłady w kodzie • Reducer • Reducer – testy • Effects • Effects – testy • Service • Service –testy • Component (smart, dumb) • Component – testy
  • 69. map-filter-reduce const array = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; const double = (x) => 2 * x; const isPrime = (n) => ...; const add = (a, b) => a + b; const doubled2 = array.map(double); const primes2 = array.filter(isPrime); const sum2 = array.reduce(add, 0);
  • 71. Wzorzec REDUX Store State ViewActions Reducer przechowuje jest projektowany na wywołuje obsługiwane przez modyfikuje https://medium.com/@flashMasterJim/setting-up-ngrx-store-in-an-angular-2-project-e5232a7b082e#.23yso3phj
  • 72. Architektura aplikacji @ngrx/Store Service Smart Comp. Dumb Comp. Reducers @ngrx/Effects Effects Service Data Service HTTP new state select state (observable) state (observable) properties (bind)events call action (dispatch) state + action action (dispatch) state + action state + action state (call) state (call)response (observable) response (observable) state + action https://youtu.be/pjwVq8B-ZAw w 21:55 i w 33:45
  • 73. Wypadałoby jeszcze wspomnieć o: • Narzędziach: Redux Dev Tools, Augury • Style guide: https://angular.io/docs/ts/latest/guide/style-guide.html • Reactive forms, reactive router, ngrx/router • Testach jednostkowych: • jednostka != plik, jednostka != klasa, jednostka != serwis • AAA – arrange, act, assert • https://angular.io/docs/ts/latest/guide/testing.html - guide • https://docs.google.com/presentation/d/1gJCBr_M5dCcCX9WUM52ZUAKVlPj 6hQv3MYXKlgFMpSA/edit?usp=sharing - przykłady • Korzystając z tej architektury celowo rezygnuje się części funkcjonalności oferowanych przez Typescript i Angular