В коде, который я пытался исправить сегодня, был такой восхитительный фрагмент:
def needs_update? bundle_command('check') $? != 0 end
Итак, давайте пойдем «ля-ля-ля» и проигнорируем зависимость от глобальной системной переменной $?.
Цель состоит в том, чтобы использовать возвращаемое значение системной команды (бандлера) для возврата логического значения из метода. Документ для команды (проверка пакета) говорит
Check ищет на локальном компьютере каждый из драгоценных камней, запрошенных в Gemfile. Если все драгоценные камни найдены, Bundler печатает сообщение об успешном выполнении и завершает работу со статусом 0. Если нет, отображается первый отсутствующий драгоценный камень, и Bundler выходит из состояния 1.
Чего он не говорит, так это того, что когда вы пытаетесь выполнить команду и что-то мешает этому, UNIX возвращает ненулевой код состояния, поэтому, если что-то еще не так, needs_update?
всегда кажется верным.
Вернемся к этому $?
. Как оказалось, это экземпляр ruby System::Status
, а не числовое значение, которое вы получили бы от bash. Так что это тоже никогда не будет нулем. $?.exitstatus
может быть тем, что нам нужно.
Таким образом, приведенный выше метод всегда возвращает true, и когда остальная часть системы работает, он без необходимости запускает установку пакета. А когда что-то ломается, он пытается и молча терпит неудачу.
- Что я всегда неправильно понимаю, так это то, почему люди не думают двойным отрицанием? …или
- Почему люди думают двойным отрицанием?
В документе говорится, что если проверка пакета возвращает 1, нам нужно выполнить установку драгоценного камня. Итак, давайте проверим наличие положительного индикатора ожидаемого состояния. Итак, $?.exitstatus == 1
, верно?
Итак, теперь, когда я начал, какого черта: методы могут возвращать значения (я знаю, типа… кто знал?).
Так почему бы этому методу bundle_command
не управлять своими внутренними компонентами и не возвращать что-то полезное. Возможно, он мог бы вернуть целое число статуса выхода.
Но, эй, если мы имеем дело с Bundler в классе (а так оно и есть), почему бы не скрыть внутренности бандлера от бедняги (меня), который должен был это выяснить, и сделать мне хороший метод bundle_needs_update?
, который возвращает true или false . Если он не получит два задокументированных кода возврата, он должен вызвать исключение. У нас все еще мог бы быть метод bundle_command(command_name), который возвращает что-то подходящее, и просто иметь симпатичную маленькую оболочку.
Это только я? Разве в школах не преподают эти действительно базовые концепции программирования?