[БЕЗ_ЗВУКА] Итак, мы начали говорить про функции, теперь наконец-то, мы можем, исходя из этого понять, какими же важными свойствами они должны обладать, чтобы считаться хорошими и чтобы код был понятным. Первое свойство — это понятность сигнатуры функции. Вы должны уметь посмотреть на сигнатуру функции и из этого понять, что же функция делает. По ее названию, по входным параметрам, по типу выходного параметра. Во-вторых, эта функция должна быть понятна в месте вызова. То есть когда функция вызывается, должно быть понятно примерно, что каждый параметр означает и чего ожидать от этой функции в привязке к этим параметрам. Затем, мы говорили про тестируемость, и конечно, функции надо писать такими, чтобы их было удобно тестировать. Понятно, что есть функции, которые вы вообще не протестируете, но и написать функцию можно настолько плохо, что тестировать ее будет неудобно. Далее, функция должна быть поддерживаемой. То есть если придет какой-то другой разработчик, или вы, и вы захотите как-то обновить функциональность этой функции, расширить ее, это должно быть легко. И наконец, связанное свойство — это сфокусированность функции. То есть функция должна решать одну конкретную задачу. Не несколько маленьких как-то переплетенно, а одну конкретную. И давайте мы сейчас все эти важные свойства проиллюстрируем несколько гипертрофированными, но тем не менее, понятными примерами на примере известных вам уже задач. Начнем с понятности сигнатуры. Вот пожалуйста. Задача «Экспрессы». В ней нужно было сделать что-то примерно следующее — там были запросы вида «добавить экспресс от одной станции до другой и проверить, насколько близко можно подъехать от одной станции до другой, пользуясь одним экспрессом». Вы эту задачу только что прорешали и наверняка вспомнили. Представьте, что вы увидите чье-то решение этой задачи и там есть функция Process. Как видите, она не принимает ничего и возвращает ничего. Какой можно вывод из этого сделать? Что эта функция делает? Совершенно непонятно, что делает эта функция, если не посмотреть внутрь этой функции. Ну давайте посмотрим внутрь этой функции, и мы увидим, что эта функция по сути просто берет и считывает все входные данные и вызывает нужные методы у переменной routes. А функция main — просто в цикле для каждого очередного запроса вызывает функция Process. То есть эта функция обрабатывает один конкретный запрос, а переменная routes при этом — вообще глобальная переменная, с которой эта функция взаимодействует. И из-за этого совершенно непонятно, что эта функция делает, если вы эту функцию не прочитаете. Вот это пример плохой функции. Она работает с глобальной переменной, она что-то читает на вход, что-то выводит и зачем здесь тогда функция — не очень понятно. Разве что ради переиспользуемости, но, пожалуйста, так не надо делать. Еще один пример функции с плохой, непонятной сигнатурой — вот такой. Задача — трекер задач, в ней нужно было как-то манипулировать задачами разработчиков, соответственно там была статистика, у какого человека сколько задач, в каком статусе, и нужно было уметь обновить статусы у набора задач для конкретного человека. Опять же, представьте, что вы видите чье-то решение этой задачи, и там вот такая функция — PerformPersonTasks, которая принимает, во-первых, словарь из строки в TasksInfo, по неконстатной ссылке, затем она принимает имя человека по констатной ссылке, это, допустим, понятно. Она принимает количество задач, которые надо выполнить, и еще две не констатных ссылки first и second на объекты типа TasksInfo. Понятно ли, что это за first и second? Ну мне, например, не понятно, если я не помню эту задачу. Еще какая-то не констатная ссылка на person_tasks. То есть функция как минимум меняет данные по трем ссылкам. Это первый аргумент функции и два последних. При этом она еще ничего не возвращает. То есть она принимает что-то на вход, а на самом деле, TasksInfo это тоже словари, и как-то она эти три словаря меняет. Кошмар. Непонятно, что происходит. Хуже того, непонятно, что такое first, что такое second. И вот эти TasksInfo, они есть как в двух последних параметрах, так и в значениях первого словаря. Вот здесь. То есть у вас может закрасться даже подозрение, что вот эти два последних аргумента — это ссылки на значения словаря. В общем, ужасно. Функция с пятью аргументами, из них еще и три неконстатные ссылки, не понятно, чего от нее ожидать. На самом деле, изначально решение было довольно приятным, с приятным интерфейсом. Там был класс TeamTasks, у него было приватное поле PersonTasks с тем самым словарем и метод — PerformPersonTasks, который принимал имя человека и количество задач и возвращал через кортеж два словаря задач со статистикой — задачи, которые сделаны, и задачи, которые не затронуты. Вот такой интерфейс был понятным. Итак. Первое свойство хорошей функции — это понятность ее сигнатуры. Возможность по ее сигнатуре понять, что же она делает: какие данные принимает на вход, какие данные возвращает. В следующем видео мы подробно рассмотрим остальные четыре свойства хороших функций.