Всем привет, меня зовут Сергей и я web разработчик. Да простит меня Дмитрий Карловский за заимствованное вступление, но именно его публикации вдохновили меня написание этой статьи.  Сегодня хотелось бы поговорить о работе с данными в Angular приложениях в целом и о моделях предметной области в частности.  Предположим, что у нас есть некий список пользователей, который мы получаем с сервера в виде а отобразить его нужно как на картинке  Выглядит несложно — давайте попробуем. Разумеется для получения этого списка у нас будет сервис UserService примерно следующего вида. Обратите внимание, что ссылка на аватарку пользователя не приходит сразу в ответе, а формируется на основе id пользователя. За отображения списка пользователей будет отвечать компонент UserListComponent. И вот тут у нас уже наметилась определенная проблема. Обратите внимание на ответ сервера. Поле last_name может быть пустым и если мы оставим компонент в таком виде, то будем получать нежелательные пробелы перед запятой. Какие есть варианты решения? Можно немного поправить шаблон отображения Но таким образом мы перегружаем шаблон логикой, и он становится плохочитаемым даже для такой простой задачи. А ведь приложению еще расти и расти... Вынести код из шаблона в класс компоненты, добавив метод типа Уже получше, но скорее всего полное имя пользователя будет отображаться не в одном месте приложения, и нам придется дублировать этот код. Можно вынести этот метод из компоненты в сервис. Таким образом мы избавимся от возможного дублирования кода, но такой вариант мне тоже не очень нравится. А не нравится потому, что получается, что некоторая более общая сущность (UserService) должна знать о структуре передаваемой в нее более мелкой сущности User. Не ее уровень ответственности, как мне кажется. На мой взгляд проблема в первую очередь возникает из-за того, что мы относимся к ответу сервера исключительно как к набору данных. Хотя ведь на самом деле он представляет собой список сущностей из предметной области нашего приложения — список пользователей. А если мы говорим о работе с сущностями, то стоит применять наиболее подходящий для этого инструментарий — методы объектно-ориентированного программирования.  Начнем с того, что создадим класс User Конструктор класса представляет собой десериализатор ответа сервера. Логика определения полного имени пользователя естественным образом превращается в метод объекта класса User равно как и логика получения аватарки. Теперь переделаем UserService так, чтоб он возвращал нам объекты класса User как результат обработки ответа сервера В результате код нашей компоненты становится значительно более чистым и читабельным. Все то, что можно назвать бизнес-логикой, инкапсулировано в моделях и является полностью переиспользуемым. Давайте теперь расширим возможности нашей модели. По идее (в данном контексте мне нравится аналогия с паттерном ActiveRecord) объекты модели пользователя должны быть ответственны не только за получение данных о себе, но и за их изменение. Например, у нас может быть возможность сменить аватарку пользователя. Как будет выглядеть расширенная такой функциональностью модель пользователя? Выглядит неплохо, но модель User теперь использует сервис HttpClient и, вообще говоря, она вполне может подключать и использовать различные другие сервисы — в данном случае это StorageService и AuthService (они не используются, а добавлены просто для примера). Получается, что если мы захотим в каком-нибудь другом сервисе или компоненте использовать модель User, нам для создания объектов этой модели придется подключать все связанные с нею сервисы. Выглядит весьма неудобно… Можно воспользоваться сервисом Injector (его конечно тоже придется внедрять, но он гарантированно будет только один) или вообще создать внешнюю сущность инжектора которую внедрять не придется, но более правильным мне видится делегирования метода создания объектов класса User сервису UserService аналогично тому, как он отвечает за получения списка пользователей. Таким образом мы переместили метод создания пользователя в UserService, который уместнее теперь называть фабрикой, и переложили всю работу по внедрению зависимостей на плечи Ангуляра — нам необходимо только подключить UserService в конструкторе. В конечном итоге давайте уберем дублирование из названий методов и введем соглашения по названиям внедряемых зависимостей. Конечный вариант сервиса в моем видении должен выглядеть так. А в компонент UserFactory предлагается внедрять под именем User  В этом случае объект класса UserFactory внешне выглядит как класс User со статическими методами для получения списка пользователей и специальным методом создания новых сущностей, а его объекты содержат все необходимые методы бизнес-логики, связанные с конкретной сущностью. На этом я рассказал все, что хотел. С нетерпением буду ждать обсуждения в комментариях. Хотел выразить огромную благодарность всем комментирующим. Вы справедливо заметили, что для решения задачи с отображением имени стоило бы использовать Pipe. Я совершенно согласен и сам удивляюсь, почему я не привел это решение. Тем не менее основная цель статьи — показать пример создания модели предметной области (в данном случае это User), которая могла бы в удобной форме инкапсулировать в себе всю бизнес-логику, связанную со своей сущностью. Параллельно попытался решить сопутствующую проблему с внедрением зависимостей.