Парадигмы 1MIT, Стандартные замечания

Материал из SEWiki
Версия от 23:40, 23 сентября 2017; E.f.suvorov (обсуждение | вклад) (Новая страница: «== Общее == === Не передавайте отдельным параметром то, что можно вычислить из остальных ===…»)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Общее

Не передавайте отдельным параметром то, что можно вычислить из остальных

Don't:

def strassen(a, b, size):
    ...

Do:

def strassen(a, b):
    size = ...

Причины:

  1. Дополнительный параметр --- дополнительное место, где можно налажать при вычислении/передаче; появляются новые инварианты, которые по-хорошему надо проверять.
  2. Сложнее отлаживать --- для тестового запуска функции требуется не просто передать массив, а ещё и его размер.
  3. Обычно такая потребность возникает при передаче кусочков матриц/массивов. Для этого обычно имеются удобные библиотечные обёртки.

Мифы:

  1. Вычислять размер каждый раз --- это медленно. На самом деле основные тормоза идут из-за сложных операций, которых много. Например, перемножение чисел или рекурсивные вызовы. Несколько обращений к памяти в не самом вложенном месте -- это нестрашно. И вообще заоптимизировать вы всегда успеете.
  2. Если не передавать размер отдельно, то нельзя работать с кусочками матриц, не копируя их. Неверно, можно просто использовать срезы. В случае с NumPy копирования во фразе mat[0:4, 0:3] не происходит - просто передаётся тот же самый кусок памяти с пометкой "используем только эту подматрицу".

Осторожно:

  1. Если вычислить этот отдельный параметр очень трудозатратно (по времени, памяти или просто по размеру кода), то может быть смысл действительно его передать. Например, если это данные, которые читаются из файла.


Проверяйте инварианты и корректность входных параметров при помощи assert

Don't:

# as и bs должны быть одной длины
def very_complex_algorithm(as, bs):
   ...
   # x + y тут должно быть равно 4
   ...

Do:

def very_complex_algorithm(as, bs):
    assert len(as) == len(bs)
    ...
    assert x + y == 4

Причины:

  1. assert'ы позволяют вам в процессе отладки быть уверенными в том, что все "очевидные" предположения выполняются. Заодно получается этакая документация.
  2. Комментарии обычно не читают. Как следствие, вашу процедуру кто-нибудь легко может вызвать с неверными параметрами (например, вы сами).
  3. Комментарии устаревают в процессе разработки программы. Если же какой-нибудь assert устареет, то он сразу упадёт и его придётся изменить.

Мифы:

  1. assert не надо использовать, потому что из-за них падает программа. Программа действительно падает, однако только в тех случаях, когда она ведёт себя не так, как вы предсказали. То есть если программа упала по assert --- то либо в ней баг, либо неверно ваше понимание о том, как она работает. В любом случае это стоит исправить.

Осторожно:

  1. Если понаставить слишком много assert'ов, код становится невозможно читать.
  2. Не стоит проверять корректность интерпретатора/компилятора. Например, после строчки a = x[2] строчка assert a == x[2] бессмысленно, равно как и проверка отсортированности массива чисел после вызова sort.
  3. Не стоит писать в assert код с побочными эффектами. Некоторые языки и/или оптимизаторы (например, Java) могут просто вырезать все assert в не-отладочном режиме.
  4. Если вы пишете production-сервис для Яндекс/Google, то падение программы нежелательно и вместо assert следует использовать другие конструкции и восстанавливать работу программы.