Angular Junior: Null Object Pattern

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Написал на Ангуляре первое приложение. Пока разобрался с RxJS и не наловил ошибок, приложение писал так, чтобы оно работало прямо и исправно. И мне помог этот паттерн. Прошу под кат.

Пример: аутентификация пользователя

Сразу к примеру. Получаем при логине пользователя, сохраняем в локал-сторадже, подписываемся на него в нужных компонентах.

// наша моделька
export class Passport {
  constructor(
    public email: string,
    public accessToken: string,
    public refreshToken: string,
    public roles: string[]
  ) {
  }
}

// Аутентифкатор
@Injectable({providedIn: 'root'})
export class Authenticator {
  private passport$: Subject;

  constructor(private http: HttpClient, private router: Router,) {
    // загружаем юзера из localstorage
    // делаем this.passport$.next(НАШ_ЮЗЕР)
  }

  public get passport(): Subject<Passport | undefined> {
    return this.passport$;
  }

Что тут не так: у нас возможно варианты, когда загрузка пользователя не прошла корректно: его еще нет, какая-то ошибка в приложении и прочее.

Это заставляет писать наш код так, что в подписчиках нужно делать фильтры и везде проставлять union-типа типы T | undefined. А еще можно забыть и много всего интересного.

Это утомительно, чревато ошибками и куче бойлерпелейта.

Исправляем:

// модель 
export class Passport {
  constructor(
    public email: string,
    public accessToken: string,
    public refreshToken: string,
    public roles: string[]
  ) {
  }
}


// Null Object, который будет у нас всегда, 
// когда нет корректного пользователя и при разлогине
export class Anonymous extends Passport {
  constructor() {
    super('anon', 'anon', 'anon', []);
  }
}


// Аутентификатор
@Injectable({providedIn: 'root'})
export class Authenticator {
  private passport$ = new BehaviorSubject<Passport>(new Anonymous())

  constructor(private http: HttpClient, private router: Router,) {
    // загружаем юзера из localstorage
    // если ошибка, в системе есть анонимный null object, 
    // который корректный тип сам по себе
  }

  public get passport(): BehaviorSubject<Passport> {
    return this.passport$;
  }

Теперь у нас всегда в аутентификаторе лежит корректный с точки зрения системы объект. Просто он без ролей, с битым некорректным токеном, но система работает прямо и корректно, можно писать более надежный и точно более постой код.

Теперь код всегда корректный, с ним мы можем писать спокойно наши интерцепторы, наши компоненты и делать HTTP-запросы на бекенд. Но тк значения не валиды, то бекенд отклонит токен, а отсутствие ролей не даст доступа к компонентам, закрытымич через Guards.

Код всегда корректен:

this.authenticator.passport
    .pipe(
        tap((passport: Passport) => {
           // тут всегда корректный тип
       })
)

Пользуйтесь :) Подход концептуальный и не является императивом.

Источник: https://habr.com/ru/post/585094/


Интересные статьи

Интересные статьи

Абстрактная фабрика - это шаблон проектирования, который позволяет создавать семейства связанных объектов без указания их конкретных классов.ПроблемаПредставьте, что мы создаем игру в которой будут ра...
«Каждый уважающий себя блогер должен написать статью о RBAC. Каждый уважающий себя читатель должен написать в комментарии, что всё равно ничего не понял». С этой фразы на...
В первой, второй и третьей частях мои коллеги рассказали, как и почему мы распиливали монолит. Если коротко, то мы создали решение, которое позволило в рамках одной ...
В 1С Битрикс есть специальные сущности под названием “Информационные блоки, сокращенно (инфоблоки)“, я думаю каждый с ними знаком, но не каждый понимает, что это такое и для чего они нужны
От скорости сайта зависит многое: количество отказов, брошенных корзин. Согласно исследованию Google, большинство посетителей не ждёт загрузки больше 3 секунд и уходит к конкурентам. Бывает, что сайт ...