Ну что ж, вот и подъехала вторая серия сериала про чистый код. Первая серия здесь.
Напоминаю, что вся эта серия постов предназначена для тех, кто изучает Python и уже имеет базовые знания. Если вы пока что не можете написать ничего сложнее `print('Hello, world!')`, то посты будут для вас слишком сложными. Поскорее изучайте основы и присоединяйтесь к движу :)
Нейминг: выбираем хорошие имена для объектов
Выбор имён для объектов - это большая тема, поэтому она будет разделена на 2 поста. Сейчас разберём общие принципы, а в следующем посте займёмся деталями.
Начнём с короткого наглядного примера.
Если от прочтения этого кода вы испытали неподдельное эстетическое удовольствие и решили впредь писать в таком же стиле, то пожалуйста, закройте этот пост, удалите интерпретатор Python и самостоятельно вызовите экзорцистов.
А если серьёзно, то этот пример должен ответить на вопрос "Зачем правильно выбирать имена объектов?". Прочитать вышенаписанный код и не истечь кровью из глаз навряд ли кому-то удалось. А теперь представьте, что вы с командой работаете над проектом, в котором 100 000+ строк кода, и всё написано в таком стиле.
Представили, поплакали, забились в угол в ужасе? Давайте успокаиваться и разбираться в том, как писать нормальный человекочитаемый код.
Самый главный принцип
Имя объекта должно чётко и коротко передавать его суть. Оно не должно быть "просто словом", которое пришло на ум в первые 5 секунд. Оно должно недвусмысленно показывать, для чего этот объект предназначен.
В примере выше есть сразу несколько нарушений этого принципа:
- аргумент "безумно полезной функции" называется `number_or_list`, хотя в реальности функция может работать только со строкой;
- имя самой функции вообще не несёт никакой смысловой нагрузки;
- имя переменной, в которой содержится сообщение, излишне длинное, ведь тот же самый смысл можно передать гораздо проще.
Алгоритм выбора имени
1. Определяете, какой смысл имеет объект;
2. Передаёте этот смысл 1-3 словами на русском, старательно отбрасывая всё лишнее;
3. Переводите на английский.
Если у вас хороший уровень английского, то пункты 2 и 3 можно совместить. Но ни в коем случае не пытайтесь это сделать, если английский у вас пока что на уровне "Лондон из зэ кэпитал оф Грейт Бритн". Имена вроде `pikture_draw` и `data_chek_completly` - это зло и боль для любого, кто будет читать код впоследствии. Не ленитесь - пользуйтесь переводчиками и словарями.
Исправляем проблему с именами
Давайте подумаем над тем, какой смысл заложен в каждый из объектов.
1. `number_or_list`: это строка, которая выводится на экран;
2. `InsanelyUseful_function_withaveryDescriptivename`: аналог `print()`, но работающий только со строками, а не с любыми объектами;
3. `incrediblylonglowercasedvariablewhichcontainsamessage`: сообщение/вопрос для пользователя.
То есть нам нужно подобрать имена для следующих сущностей:
- строка/текст;
- напечатать строку;
- сообщение/вопрос.
Переводим на английский и получаем следующие варианты:
Выбор конкретного варианта остаётся на ваше усмотрение, но есть пара нюансов.
1. Если используется 1 переменная со смыслом "просто объект", то можно использовать однобуквенное имя `s` как сокращение от `string`. Например:
Здесь неважно, какая строка передаётся в функцию. Строка и всё, никакого особого смысла у неё нет. К тому же функция короткая и принимает всего 1 аргумент. Поэтому можно смело использовать `s`.
2. Если же производится работа с несколькими разными сущностями, или у сущности есть конкретный узконаправленный смысл, то лучше использовать более наглядное имя. Сравните:
То же самое в случае с одним аргументом, имеющим конкретный смысл:
Разбор заданий из предыдущего поста
Исходный пример в этом посте был искусственным, проблемы с неймингом в нём были доведены до абсурда. Поэтому давайте разберём конкретные решения, которые вы отправляли в прошлый раз.
Важно: если окажется, что у вас не получилось сразу выдать отличные имена для функции и её аргументов, не расстраивайтесь. Не ошибается лишь тот, кто ничего не делает. Со временем вы научитесь подбирать хорошие имена для объектов, если будете целенаправленно над этим работать.
Вот имена, которые разные пользователи подобрали для функции, разбивающей IP-адрес на 4 октета:
Самая распространённая проблема - это вложение в функцию смысла "проверяльщик IP". Но ведь её основное назначение - не проверка, а извлечение октетов из IP-адреса и возврат кортежа. Проверка самого адреса - это лишь косвенное действие. Название объекта не соответствует его смыслу.
Наиболее интересный вариант - это `checker(string)`. Судя по названию, функция проверяет строку. В чём именно заключается проверка и что это за строка - неясно. Чтобы понять, для чего нужна эта функция, придётся полностью разбирать её исходный код.
Были и другие варианты:
Вариант с `parse_ip(ip)` наиболее близок к идеальному. Лаконично, стилистически корректно, отлично передаёт суть. Возможные аналоги: `extract_octets(ip)`, `split_ip(ip)`.
Остальные варианты тоже неплохи, но имеют некоторые недочёты, которые будут разобраны в следующей серии.
Новая задачка
Напишите функцию, которая будет подсчитывать количество книжных страниц, необходимых для размещения текста. На вход она должна принимать строку, а на выходе возвращать целое число.
Критерии для расчёта:
- максимум 50 строк на 1 странице;
- максимум 55 символов, включая пробелы, в 1 строке.
Значения "50" и "55" пока что можно захардкодить, то есть вручную написать в коде программы. Но если хотите, можно сделать их параметрами функции.
Обязательно подумайте над именами объектов. Самое главное в текущем задании - это не супер-крутой алгоритм, а хорошие названия. Над алгоритмами и декомпозицией задач поработаем чуть позже.
UPD: учитывайте, что в настоящем тексте будут переносы строки `'\n'`. Изначально не указал это, подумав, что все сами догадаются :)
Как оформлять решение
Должно быть изображение, а под ним ссылка на код. В прошлом посте вместо ссылки на код делали цитату, но это оказалось неудобно, т.к. Пикабу нещадно кромсает отступы.
1. Изображение из кода генерируется с помощью https://carbon.now.sh/
2. Ссылка на код - с помощью https://www.codepile.net/ или аналогичного ресурса.
Решения, оформленные в стиле тяп-ляп, в разбор гарантированно не попадут, потому что их неудобно читать и на работу с ними уйдёт много лишнего времени.
Как и раньше, приоритет в разборе отдаётся подписчикам. Для меня это признак того, что вам действительно интересна эта тема и вы будете ждать следующих постов.
Надеюсь, пост был полезным и интересным :) Если что-то не так - пожалуйста, напишите в комментариях. Обратная связь очень важна, я хочу делать максимально качественный контент для вас.