Исследование длинных списков параметров

День 14 конкурса качества кода Бена Оренштейна

Начну с небольшого признания: в моей кодовой базе есть метод, который принимает 11 аргументов.

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

  1. Если вы передаете методу 11 аргументов, вы почти наверняка нарушаете принцип единой ответственности. Как часто методу, у которого есть только одна обязанность, требуется 11 различных битов информации для выполнения этой обязанности?
  2. О длинных списках параметров трудно рассуждать. По мнению умных людей, мы можем одновременно удерживать в рабочей памяти только семь вещей. Выйдите намного дальше этого, и вы начнете бороться. У вас закончилась оперативная память, и теперь вы нажимаете файл подкачки.

Если вы ищете свой код с помощью регулярного выражения /\(.*,.*,.*,.*\)/, вы можете найти любой метод, который принимает четыре или более аргументов. Для Rubyists многие люди на челлендж-форуме рекомендовали гем reek, который просматривает ваш код и выявляет запахи кода. Если у вас есть метод, который принимает большое количество аргументов, рассмотрите следующие способы его уменьшения:

Параметры, которые должны быть переменными экземпляра

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

Сгустки данных

У вас есть наборы параметров, которые часто передаются вместе? Может иметь смысл извлечь их в содержащий объект. Классический пример — передача координат x и y методу.

def foobar(x, y)
  # ...
end
foobar(1, 2)

Каждый раз, когда вы используете этот метод, вам придется указывать аргументы x и y в правильном порядке. Это можно упростить, если метод принимает наш новый класс Point в качестве единственного параметра.

def foobar(point)
  # ...
end
foobar Point.new(1, 2)

Это имеет несколько преимуществ. Мы можем расширить поведение класса Point, не меняя сигнатуру метода foobar. Мы можем изменить сигнатуру метода foobar, не путая, какая часть списка аргументов соответствует нашим координатам. Все выигрывают.

Муфта управления

Если метод принимает флаг, который радикально меняет его поведение, вероятно, должно быть два метода. Подробнее об этом читайте в статье Этот превосходный мыслебот.

Дальнейшее чтение

Этот пост является частью моей серии, следующей за 30 Day Code Quality Challenge Бена Оренштейна. Любая полезная информация, найденная в этих сообщениях, полностью благодаря ему и другим замечательным людям на форуме задач.