ngular

pp

rchitecture

with 5 Simple Concepts.

💣

-  AAA QUALITY JOKE

AGENDA:

Architecture q&a

Popular concepts

Live Coding Examples 🔥

    Approach

Konstantin Malikov

Angular Workshop

Angular Minsk

Participant:

quarantine

Happiness

Success

Love

Architecture

важное уточнение:

не NX

не ngrx

не prettier

не tslint

WHY & goals TO DO

Scalability

Code consistency

Decrease development time

Be prepared for ngxs/ngrx

Better architecture

Ease up onboarding

project lifecycle

goals NOT TO DO

Complexity

Threshold

Redundant boilerplate

Low maintainability

Increasing time to do features

hold on these 3 layers:

Presentation layer

@Component({
  selector: 'app-toolbar',
  template: `
    <div class="toolbar">
      <i class="check-square" (click)="checkAll()"></i>
      <i class="trash" (click)="deleteChecked()"></i>
      <input type="text" #input (input)="filterTodos(input.value)">
    </div>`,
  styleUrls: ['./toolbar.component.scss']
})
export class ToolbarComponent {
  /* only Facades and NO States, NO other services */
  constructor(private todoFacade: TodoFacade) { }

  checkAll() {
    this.todoFacade.toggleAllTodos();
  }

  deleteChecked() {
    this.todoFacade.deleteAllTodos();
  }
}

Abstraction layer

@Injectable({ "providedIn": "root" })
export class TodoFacade {
  /* only States, services and other Facades (!) */
  constructor(private todoState: TodoState) { }
  
  todos$ = this.todoState.todos$;

  deleteTodo(todo: Todo): void {
    const todos = this.todoState.getTodos$();
    this.todoState.setTodos(
      [...todos.filter(x => x !== todo)]
    );
  }
}

Without abstraction layer

With abstraction layer

Core layer (state)

@Injectable({ "providedIn": "root" })
export class TodoState {

  private todos$ = new BehaviorSubject<Todo[]>(sampleTodos);
  private filter$ = new BehaviorSubject<string>('');
  private updating$ = new BehaviorSubject<boolean>(false);

  getTodos$(): Observable<Todo[]> {
    return this.todos$.asObservable();
  }

  setTodos(todos: Todo[]): void {
    this.todos$.next(todos);
  }

  isUpdating$(): Observable<boolean> {
    return this.updating$.asObservable();
  }
}

Core layer (async service)

@Injectable({ "providedIn": "root" })
export class TodoApiService {
    
    constructor( private httpClient: HttpClient ) { }

    getTodos(): Observable<Todo[]> {
        const url = `${environment.apiServer}/todos`;
        return this.httpClient.get<Todo[]>(url);
    }
}

5 most common concepts

(1 / 5)

Facade on

Module level

Facade on

Component level

Decouple presentation from core layer

Sandbox for components

Facade pattern

(1 / 5)

(2 / 5)

@Input()

@Output()

Observable

App Data

functions

Actions

(to update state)

Unidirectional data flow

(2 / 5)

2

3

1

4

5

(3 / 5)

App Data

Observable streams

Data Consistency

"The single source of truth"

(3 / 5)

Reactive state management approaches:

userList$ = new BehaviorSubject<User[]>([]);

NGRX

(4 / 5)

Modular design

Share

Lazy load

Preload

Wrap components

(5 / 5)

Parent component

Wrap child components

Communicate with core (through facade)

Pass data to child component

React to child component

(5 / 5)

Child component

Presentation

@Input()

@Output()

No business logic

1 recommendation

И все заработает?

Reinventing the wheel?

Angular Ecosystem

Angular Architecture with 5 Simple Concepts

By Konstantin Malikov

Angular Architecture with 5 Simple Concepts

Angular Architecture with 5 Simple Concepts

  • 240