29 septembrie 2022

KOTLIN - ziua 2

Fisier kt -> .class file

Rulare:

> java -cp ...\kotlin-runtime.jar MainKt 

Alta optiune: export jar

> java -jar MainKt.jar


Mai putina "ceremonie":

- poti defini clase oriunde, nu trebuie sa fie in fisier separat


STRINGS

- string interpolation: 

  println("Display $name")

  println("Display $(obj.name)")

- string comparison: if (str1 == str2)

- nullable vs non-nullable

  var answer: String// non-nullable

  var answer: String?// nullable

- string comparison with null check: if (str1?.prop == str2?.prop) // compara doar daca nu sunt nule


IF este o expresie care returneaza o valoare:

var message = if (str1 == str2) { "egal" } else { "gresit" } 


WHEN - asemanator cu switch

 when (str1) {

  "25" -> print("Corect")

  else -> print("Gresit")

}


TRY - CATCH

val num: Int = try {
Integer.parseInt("20s")
} catch (e: NumberFormatException) {
-1
}
finally {
}


Iteratii - WHILE, FOR

var range = 1..10 // inclusive
// poate fi si range = 'a'..'z' --- orice care implementeaza interfata Comparable

for (i in range step 3) {
println(i)
}
for (i in 10 downTo 1 step 4) {
println(i)
}
for (i in 1 until 10) { // non-inclusive
println(i)
}


LISTE

var nums = listOf(11,22,33)
for (i in nums) {
println(i)
}
for ((index, element) in nums.withIndex()) {
println("$element at index $index")
}


MAPS

var ages = TreeMap<String, Int>()
ages["Geo"] = 33
ages["Petri"] = 7
for ((name, age) in ages) {
println("$name's age is $age")
}

22 septembrie 2022

KOTLIN - ziua 1

KOTLIN este un limbaj OOP simplificat (cu mai puține linii de cod), care acomodează mai bine decât Java paradigma funcțională (fiind chiar limbaj funcțional) și care rulează pe JVM. Considerat o îmbunătățire a Javei.

> kotlinc hello.kt

Creează un fișier .class

> kotlinc hello.kt -include-runtime -d hello.jar

> java -jar hello.jar

Creează un jar și rulează java


var (înaintea declarării unei variabile) vs val (declară variabila immutable)

public este implicit în Kotlin

void este Unit


fun main (args: Array<String>) {
println("Hello world")

val geo = Person("Georgiana")

geo.display1()
geo.display2(::displayHelper)
}

fun displayHelper(name: String) {
println("Bravo $name")
}

class Person (var name: String) {
fun display1() {
println("Display $name")
}

fun display2 (func: (s:String) -> Unit) {
func(
name)
}
}

16 septembrie 2022

javax.validation

Un tutorial util: Spring MVC Custom Validation

Pont: se va adnota cu @Valid fiecare obiect care trebuie verificat (inclusiv in cascada, mergand pana la obiectul final ce contine adnotarea cu constrangere - cum era @ContactNumberConstraint)

--------------------------------

package secret***.controller;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class RandomValidator implements ConstraintValidator<RandomConstraint, String> {

@Override
public void initialize(RandomConstraint contactNumber) {
}

@Override
public boolean isValid(String value, ConstraintValidatorContext cxt) {
return value != null && value.matches("[0-9]+")
&& (value.length() > 8) && (value.length() < 14);
}
}
--------------------------
package secret***.controller;

import java.lang.annotation.*;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = RandomValidator.class)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RandomConstraint {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
--------------------------
@PostMapping("/save")
public ResponseEntity<VrDeResultDTO> save(@RequestBody @Valid ContextDTO contextDTO) {
return new ResponseEntity<>(choreographer.save(contextDTO), HttpStatus.OK);
}
--------------------------
in ContextDTO ---> toate campurile care duc la campul adnotat cu @RandomConstraint trebuie sa aiba @Valid.

08 august 2022

Angular Architecture & Best Practices - ziua 5

Alte considerații

== înlocuire funcții cu pipes - se cheamă doar când se schimbă datele de intrare

{{ product.price | addTax | currency }}

@Pipe({

    name: 'addTax'

})

export class AddTaxPipe implements PipeTransform {

    transform(price: number): number {

        // cod 

    }

}


== Memo Decorator - ajută la caching în funcția de transform a unui pipe, când se trimite un parametru primitiv 

- dacă se repetă parametrii, ține minte rezultatul

- reies mai puține apeluri 

import memo from 'memo-decorator';

...

@memo

transform(price: number): number {

    // cod 

}


Operatori HttpClient & RxJS 

== switchMap: "switch to a new observable" -  după ce primește rezultat de la un Observable, anulează subscripția, trece la următoarea

return this.http.get(url)

         . pipe(switchMap (param1 => {

             return this.http.get(param1['param2']) // conține un url pt a obține date suplimentare

               .pipe (map (res2 => {param1['param2'] = res2; return param1;}))

      }));


== mergeMap: nu anulează inner subscripțiile, permite mai multe, nu garantează ordinea elementelor (concatMap face asta)

return this.http.get(url).pipe(switchMap (...), mergeMap (...), toArray);


== forkJoin: când toate apelurile s-au finalizat, întoarce un array cu rezultatele lor

return forkJoin (this.getA(), this.getB())

          . pipe (map ((res) => {return {val1: res[0], val2: res[1]}}));


Securitate

== CORS (Cross-origin Resource Sharing) - pe server se stabilesc domeniile/porturile de pe care poate primi request (trebuie să limiteze explicit domeniile, header-ele și metodele permise, ex. GET, POST, etc)

== CRSF (Cross-site Request Forgery) 

- pt prevenire se activează CSRF pe server dacă se folosește autentificarea prin cookie-uri 

- Angular va folosi token-ul primit în cookie-urile trimise de server pt a îl adăuga în header-ul de request (doar Angular poate face asta).

== Route Guards - OK, dar nu furnizează securitate

== Transmitere date secrete din Angular: NOK; dar se poate crea un API intermediar care să împacheteze secretul și să-l trimită la API-ul destinatar. Folosire tokeni JWT cu dată de expirare.


Interceptori HTTP

Interceptează requests / responses și atașează date în plus (ex. de tokeni de securitate).

authReq - request-ul îmbunătățit cu noi date

withCredentials - adăugat când se folosesc cookies & CORS

next.handle - predă ștafeta la următorul interceptor, dacă există


Se declară în core.module.ts. 

15 iulie 2022

Angular Architecture & Best Practices - ziua 4

State Management

Opțiuni: servicii, NgRx, ngrx-data, observable store

Altele neabordate: Akita, Ngxs, MobX

Tipuri de stare: specifică aplicației / sesiunii / de business


Servicii Angular

Este cea mai simplă metodă. 

Mai multe servicii pot avea legătură la un storage comun. 


NgRx 

  • reactive state management inspired by Redux; unify the events & derive state using RxJS
    • Redux + RxJS = NgRx 
    • Redux - popularizat de Facebook și React
  • o singură sursă de adevăr în privința stării datelor
  • furnizează date immutable
  • cost: complexitatea codului



// în componentă:

constructor (private store: Store<EntityState>) {} 

this.store.dispatch (new CustomerAction.GetCustomers()); // 1 

// customer.reducers.ts  cheamă servicii 

// customer.effects.ts  este un @Injectable și are metode adnotate cu @Effect care ret. un Observable

// customer.selectors.ts  face subscribe la Store, furnizează rezultatul în componentă


ngrx-data = NgRx simplificat, un wrapper (mai puțin cod - o linie de cod/entitate)


Observable Store

== pachet: @codewithdan/observable-store

== sursă unică a datelor, read only, notificări la schimbare de stare către cei care s-au abonat, păstrează un istoric al schimbării de stare (onBefore, onAfter), cod puțin & funcționează cu orice framework

== inclus într-un serviciu care extinde ObservableStore<TipulDeDate>

== include starea (TipulDeDate) prin this.getState()

Inițializare prin this.setState(data, actionName); // acțiunea se salvează pt logging

== componenta face subscribe la Observable store