Тестовое задание на Angular. Заключение.
Краткий обзор проделанной работы при написании тестового задания.
В процессе работы было создано микроприложение для бронирования номера в гостинице или апартаментах.
Базовое приложение было сгенерированно с помощью стандартных 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