Скажем, нам нужна функция, которая "зажимает" значение переменной в данном промежутке. Если промежуток [20, 255] а переменная x, то фунция вернет x без изменений когда он между 20 и 255, вернет 20 если он меньше 20, и 255 если он больше 255.
Первый вариант: clamp(x, low, high)
В чем недостаток этого API? Подумайте перед тем, как читать дальше.
Ответ: в момент вызова трудно вспомнить, как правильно вызвать: clamp(x, 20, 255) или clamp(20, 255, x). Оба варианта могут показаться "логичными". Все три аргумента одного типа - компилятор не остановит неправильный вызов, и он может привести к неправильному поведению.
Второй вариант: mid(x, y, z). Фунцкия возвращает среднее из трех значений, неважно, в каком порядке их расположить. Оказывается, это делает ровно то, что требуется от clamp(). Красиво!
В чем недостаток этого API? Подумайте перед тем, как читать дальше.
Ответ: во время чтения кода намерения автора (intent) неясны. Да, mid() сделает "зажим", но то, что она делает зажим - некая нетривиальная мысль, ее надо продумать и перебрать в голове, если сам это не написал, или если написал больше, чем неделю назад и уже забыл. Можно оставить комментарий возле каждого вызова mid(), но и у этого есть очевидная, хоть и небольшая, цена с точки зрения читаемости и понятности кода.
Третий вариант: оставить название clamp(), но делать то, что делает mid(). Иными словами, делать больше проверок внутри кода функции, чтобы точно вернуть среднее из значений. clamp(x, low, high) может уже точно знать, что вернуть, если прошла проверка if (x > high), но в этом варианте мы обязательно делаем минимум два сравнения.
В чем недостаток этого API? Подумайте перед тем, как читать дальше.
"Неправильный" порядок аргументов теперь не может привести к неверному поведению, и единственная проблема с порядком, которая остается - это что во время написания кода мы все равно можем задуматься и затормозить, потому что неочевидно, в каком порядке их писать. То, что мы добавили безопасности, отлично, но для программиста, который подозревает проблему и пытается разобраться, мы ничего не сэкономили - он найдет имплементацию/документацию и увидит, что все равно, в каком порядке, но с таким же успехом он первоначально мог проверить документацию и поставить правильный порядок. Тем не менее, этот вариант все равно намного лучше первого тем, что защищает от программиста, который не задумался. То, что функция работает медленнее из-за большего числа сравнений, отметаем, как абсолютно неважное за исключением крохотного числа специализированных контекстов, где нам сознательно важно писать супер-оптимизированный код низкого уровня.
Из этих трех вариантов я выбираю третий.
Хотелось бы что-то еще лучше - каков он четвертый вариант? В языках, позволяющих именные параметры, можно написать clamp(x, low=20, high=255), но это относительно редко встречается. Какие будут еще предложения?
← Ctrl ← Alt
Ctrl → Alt →
← Ctrl ← Alt
Ctrl → Alt →