Как писать объектно-ориентированный код, сохранив волосы на голове
Подборка советов от разработчика в 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.