Как писать объектно-ориентированный код, сохранив волосы на голове

0
6200

Подборка советов от разработчика в Fueled по написанию объектно-ориентированного поддерживаемого кода. Они позволят вам писать код, сохраняя волосы и нервы.

Шаблон Starter – Версия Android

Создание

Обычно мы создаем объекты в одном месте. Это может быть конструктор, шаблон проектирования строитель, фабричный метод, абстрактная фабрика или вообще любой из порождающих шаблонов.

Бывает так, что объекты, созданные фреймворком, нуждаются в дополнениях. В нашем примере на Android это класс Activity. Он создан фреймворком Android, и добавить атрибуты мы можем только через Intent.

DRY (Don’t Repeat Yourself)

В течение продолжительного времени, начиная Activities и добавляя дополнения, я привык писать комментарий в начале класса Activity, упоминая все, что требовалось для его правильной работы. Что-то вроде:

На мой взгляд подобные комментарии – это хорошая документация. Мне нужно было запустить TargetActivity из разных входных точек через множество классов и startActivity(intent) было написано везде. Поэтому DRY запрещено: не повторяйтесь.

С ростом команды и увеличением кода, множество вещей может случиться с классом:

  • Появятся новые дополнения
  • Комментарии перестанут совпадать с дополнениями
  • Ваша команда может забыть передать некоторые дополнения
  • Вы можете забыть добавить новые дополнения к старым вызовам

Статический Starter

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

В Android Studio есть встроенный шаблон для starter:

Это помогло мне избежать путаницы в проекте в 150000 строк кода. Надеюсь это поможет и вам.

Смерть от аргументов

Аргументы, аргументы, аргументы

  • Слишком длинный список аргументов функции утомляет код. Также из-за этого становится легко передать их в неправильном порядке, а еще ухудшить читабельность кода.
  • Пока вы не прочитаете подпись функции дважды, вы ничего не поймете.
  • Аргументы затрудняют проверку функции. Трудно написать все тестовые примеры, обеспечивающие правильную работу всех комбинаций её параметров.

Поэтому мы должны избегать безрассудного отношения к аргументам и быть ответственными за каждый.

Структура

Лучшие функции имеют минимальное количество аргументов. В идеале — ноль.

0-местная > 1- местная > 3- местная > многоместная

Подобное руководство применимо и для конструкторов.

Всегда помните о рефакторинге

  • Аргументы и Объекты: если вы передаете более трех аргументов в ваших функциях, остановитесь и подумайте. Если три и более переменные настолько едины, что передаются вместе, то почему они не являются объектом?
  • Перегрузка: одной из причин перегрузки функций является то, что клиент может вызвать необходимую версию функции, используя лишь нужные параметры.
  • Шаблон строитель: иногда перегрузка функций выходит из-под контроля, что ведет к ситуации, называемой телескопический конструктор. Чтобы его избежать, Джош Блох во втором издании «Java. Эффективное программирование.» ввел использование шаблона Строитель для работы с конструкторами, которые требуют слишком много параметров.
  • Мутируемое состояние: не рекомендуется. Возможно наиболее известный и самый презираемый подход в разработке — это использование глобальных переменных экземпляра для уменьшения параметров функции. Хоть это и не лучшее решение, в некоторых случаях оно допустимо. Используйте осторожно, особенно во многопоточных программах.

Смерть из-за Boolean

Чаще всего, когда вы передаете boolean в функцию, вы громко заявляете всему миру, что написанная функция, делает две вещи. Первую в случае true, вторую в случае в false. Вместо этого вы должны написать две функции, по одной для каждого исхода.

Boolean в списке аргументов может породить множество ошибок и путаницу. Что значит, если true? Что значит, если false? Если название функции и аргументы не объясняют это доходчиво, тогда каждый раз при вызове функции вам нужно будет глубоко нырять в детали реализации для того, чтобы понять какое значение передать. Если же передавать два параметра boolean все становится еще хуже. Попробуйте угадать порядок boolean и поведение:

Заставляет вас жмуриться, не так ли? Чтобы избежать догадок и двойных просмотров используйте шаблон строитель:

Нулевая защита

Передача null в функцию или написание функции, ожидающей null, почти так же плохо, как передача в нее boolean. На самом деле, это еще хуже, поскольку совершенно не понятно, что существует всего 2 возможных состояния. sКонечно, есть вариант для значения, отличного от нуля и один для нулевого. Лучше всего создать две функции: одну, которая принимает ненулевой аргумент, а другая — вообще не принимает этот аргумент. Не используйте значение null, как псевдо-boolean.

Давайте будем честны. Защитное программирование — отстой. Это ужасный, грязный код с проверками ошибок и проверками null. Мы не хотим думать, что наши коллеги беспечно дали проскользнуть null в наши функции. Также это означает, что мы не верим, что наши юнит тесты предотвратят передачу этого null.

Послушайте Гендальфа. Null аргументы не должны пройти. Это не относится к публичным API-интерфейсам, так как мы не знаем, кто что передаст. Если ваш язык поддерживает аннотацию @NotNull или аналогичную концепцию, используйте ее, чтобы отметить свои общедоступные функции, и вы получите быстрый fail fast, выбросив что-то вроде IllegalArgumentException.