Тестовое задание на Angular. Заключение.

Aleksandr Serenko
F.A.F.N.U.R
Published in
4 min readJul 5, 2021

Краткий обзор проделанной работы при написании тестового задания.

В процессе работы было создано микроприложение для бронирования номера в гостинице или апартаментах.

Базовое приложение было сгенерированно с помощью стандартных Angular Cli. После создания приложения, были определены style guide и подключен eslint и включен prettier. Также следуя современным тенденциям и рекомендациям NX, был изменен тестовый фреймворк на Jest.

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

Закончив с созданием шаблона в приложение был подключен Redux, который взял на себя обязанности управления данными. Был создан RootState (Store), который по умолчанию включил в себя только модуль с хранением данных о навигации пользователя (routerState).

Так как тестовое задание подразумевало хранение данных, были созданы интерфейсы и классы для взаимодействия со стандартными хранилищами (localStorage, sessionStorage).

После этого были определены базовые интерфейсы в приложении: Room, Building и Person, которые отображали апартаменты, здания и собственников соответственно.

Данная структура была выбрана специально, чтобы продемонстрировать связь между разными сущностями. В реальных проектах, архитектура приложения будет совершенно другой, в зависимости от места, страны и времени.

Для каждой из базовых сущностей были созданы соответствующие state’ы, которые приняли на себя все CRUD операции с данными.

Затем была определена сущность “бронирования”, которая включала в себя одновременно все базовые сущности (вновь для демонстрации работы между разными сущностями). Бронирование получило свой state, а также ряд сервисов.

Так как логика приложения была определена, то появилась потребность в создании UI-kit’а, который мог бы использоваться во всем приложении. Тогда были созданы общие компоненты и сервисы: спиннер, карусель, сетка и другие.

После разработки UI, была реализована страница бронирования для двух экранов: мобильного устройства и настольного компьютера.

На странице бронирования отобразили полный список доступных вариантов, а также карту, на которой отметили доступные варианты. В мобильной версии сделали переключатель со списка на карту и обратно.

Для апартаментов создали страницу с детальной информацией. На данной странице вывели информацию о бронировании и форму, где можно выбрать срок и количество гостей и узнать стоимость.

Затем создали лейаут для админ панели. Используя данный макет создали страницу редактирования апартаментов. Можно удалить все апартаменты, а также создать новые. Аналогично добавили страницы для Building и Person.

В конце были написаны тесты для сервисов и компонентов. В первую очередь тестировались сервисы, в частности работа Redux, так как это одно из тонких мест приложения. Затем проверялась связка HTML и JS, проверяя корректность работы Redux в шаблонах и компонентах.

Невошедшее в цикл

Статьи которые не вошли в туториал, но функционал которых был реализован:

  • Настройка environment’ов — создание универсального сервиса
  • Настройка локального deploy’я с помощью создания контейнеров (docker) и управления ими с помощью docker-compose
  • Описание процесса git flow
  • Обзор второстепенного функционала, который не влияет на работу приложения (numerals, nx fetch)
  • Обзор админ страниц для Booking и Person

Функционал, который был убран из приложения или не реализовывался:

  • SSR — реализация server side rendering с помощью Angular Universal
  • SEO — реализация seo для сайта (мета теги, метрики)
  • Analytics — реализация собственного решения для логирования действий пользователя, на основе отслеживания заполнения форм, переходов по страницам и смены фокуса.

Нюансы

Самое главное в тестовом задании:

  • Оно должно запускаться
  • Оно должно реализовывать поставленную задачу, хотя бы частично.

Как бы не казалось парадоксальным, периодически попадаются проекты, которые не запускаются, или запускаются но сыпят ошибками в console.

Важные нюансы при ревью проекта, которые не связаны с тестовым заданием, а с хорошими практиками:

  • Весь код написан в одном стиле и линтер не ругается (ng lint)
  • Весь код покрыт тестами (хотя бы даже автосгенерированными, но валидными — ng test)
  • В проекте нету неиспользуемого кода
  • В проекте современный стек и технологии (jest, nx, …)
  • В проекте есть документация (readme.md — где описан весь процесс разворачивания и запуска проекта)
  • В проекте есть история в gite (всегда хочется посмотреть как и сколько делался проект)
  • В проекте минимум внешних зависимостей (то, что не разрабатывается team core)

При ревью кода, всегда внимание уделяется вниманию разделению кода. В Angular это работа с данными и компонентами. Первое на что смотрят это реализация логики.

Все обработки данных должны быть в pipe. Ниже пример, который должен быть вынесен в pipe.

Неверно:

{{ getAmount(price.amount) }}///getDay(amount: number, discount: number = 100): string {
return discount < amount ? amount - discount : 0;
}

Верно:

{{ price | amountWithDiscount }}///export class AmountWithDiscountPipe {
transform(amount: number, discount: number = 100): number {
return discount < amount ? amount - discount : 0;
}
}

Все сложные вычисления должны быть в сервисах:

Неверно:

export class AppComponent {
price!: number;

constructor(
private readonly booking: BookingService,
private readonly discount: DiscountService
) {}

ngInit(): void {
this.price = this.booking.variant - this.discount.discount;
}
}

Верно:

export class PriceService {
constructor(
private readonly booking: BookingService,
private readonly discount: DiscountService
) {}

get price(): number {
return this.discount.discount > this.booking.price ? this.booking.price - this.discount.discount : 0;
}
}
///export class AppComponent {
price!: number;

constructor(private readonly priceService: PriceService) {}

ngInit(): void {
this.price = this.priceService.price;
}
}

Angular Router не предоставляет дефолтных страниц при ошибке навигации, поэтому, в роутинге либо должен быть редирект на главную или явное показание страницы 404.

Еще один важный показатель это использование RxJS. Весь Angular построен на RxJS и если его не использовать, то все преимущества Angular сводятся на нет.

Ссылки

Вернуться к оглавлению — Введение.

Предыдущая статья — Тестирование компонентов.

Все исходники на github/fafnur/barinb.

Группа в Medium: https://medium.com/fafnur
Группа в Vkontakte: https://vk.com/fafnur
Группа в Facebook: https://www.facebook.com/groups/fafnur/
Telegram канал: https://t.me/f_a_f_n_u_r
Twitter: https://twitter.com/Fafnur1
LinkedIn: https://www.linkedin.com/in/fafnur

--

--

Aleksandr Serenko
F.A.F.N.U.R

Senior Front-end Developer, Angular evangelist, Nx apologist, NodeJS warlock