Паттерн «объект-значение»
фото: shuttermanic
17 октября 2012 года Bryan Helmkamp, основатель Code Climate написал
пост описывающий 7 паттернов для рефакторинга толстых ActiveRecord
-моделей
в Ruby on Rails. Здесь, в Crush & Lovely, у всех Rails-разработчиков этот пост
является основным ориентиром для написания модульного, лаконичного, выразительного
и тестируемого кода.
В этой серии статей мы расскажем о подобных концепциях в JavaScript. Как и работа Bryan Helmkamp, эта серия так же применима к моделям данных, и не менее полезна. Начнем с паттерна «объект-значение».
Паттерны рефакторинга JavaScript-приложений
- Объект-значение
- Объект-сервис
- Объект-форма
- Объект-запрос
- Объект-представление
- Объект-политика
- Декораторы
Объект-значение
В статье Brayan’а объект-значение описывается как «простой объект, который сравнивается по значению, а не по идентификатору». Поскольку в JavaScript все объекты передаются по ссылке, подобных примеров, за исключением примитивов, нет ни в ECMAScript 5, ни даже в Harmony. Например:
В этом примере примитивы сохраняются в переменные foo
и bar
, которые равны
по значению, но, технически, эти примитивы являются объектами. Конструктор Number
,
не смотря на то, что он создает примитивный элемент, создаст «простой JavaScript-Object
в старом стиле» (POJO), потому переменные сравниваются по ссылке, а не по
значению и не будут равны между собой, хотя имеют одинаковое значение.
Объект-значение — это хорошее место для размещения бизнес-логики. Практически любое значение в вашем приложении имеет ассоциированную с ним логику, к примеру, проверку равенства, и лучшее место для этой логики — инстанс объекта-значения.
Пример
Рассмотрим приложение по классификации студентов, где студент получает баллы в процентах, определяя по ним буквенную оценку и то, проходит ли он дальше, или ему пора исправляться.
Подобная структура дает дополнительное преимущество, делая ваш код более выразительным. К примеру, теперь можно пистать так:
Перед тем как интегрировать объекты-значения в приложение, стоит отметить несколько вещей:
- Методы
valueOf
иtoString
выполняют специальную роль, и рекомендуются для создания собственных объектов-значений. Применив его вGrade
-объекте выше, мы добавили ему поддержку стандартного ECMAScript-синтаксиса, что позволило нам писать такие конструкции:
К сожалению, даже если два различных объекта возвращают одинаковое значение
с помощью valueOf
, они все равно не будут равны.
-
При конвертировании объекта-значения с помощью
JSON.stringify
, согласно конвенции, используетсяtoJSON
-метод, возвращающий значение, которое будет использовано при конвертировании в строку. Если же методtoJSON
не определен, то будет использованvalueOf
. ЕслиvalueOf
нет — объект будет конвертирован какObject
, что, зачастую, не желательно. -
Хороший паттерн — использовать
valueOf
для возвращения значения, с которым объект был инициализирован, что позволяет воссоздать этот объект с другой стороны транспорта, что очень полезно если приложение имеет клиент и сервер, между которыми передаются объекты-значения. Используя простое значение объекта на входе и на выходе, вы можете взаимодействовать с объектом-значением на сервере, затем отправить значение на клиент, используяvalueOf
, и воссоздать там объект заново. -
Если вы предпочитаете более функциональный подход к объектам-значениям, то вы можете добавить методы в функцию-конструктор вместо ее прототипа. Посмотрите на следующий пример:
И объектно-ориентированный, и функциональный подход, являются допустимыми. Все зависит исключительно от вашего стиля.
Тестирование
Так как этот паттерн централизует логику в единый объект, тестирование значительно ускоряется и упрощается. К тому же, требуется гораздо меньше тестов для покрытия большей части логики приложения. Посмотрите сами:
Одно из преимуществ тестирования объекта-значения в том, что сетап для тестирования максимально прост. Тестирование различных взаимодействий получается простым и эффективным, позволяя избежать создания специальных моделей и написания сложной логики. В добавок, логика изолируется от любых тестов моделей, что позволяет держать тесты компактными и специализированными
В следующем посте мы рассмотрим сервисные объекты, которые являются хорошим инструментом для изолирования процедурного кода.
Подписывайтесь на РСС. Всем добра и вкусняшек!
фото: shuttermanic
Похожие статьи:
-
Паттерн «объект-представление»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-запрос»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-форма»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-сервис»
7 паттернов для рефакторинга JavaScript-приложений
-
Чейнинг
или Как сделать код проще, добавив одну строчку
-
Музыка для работы #5
Немного мурашек по спине…