Найти в Дзене
КиберMamedov 💻🔥

Как писать хороший код используя библиотеки

Оглавление

Если тебя заинтересовал заголовок, значит ты программист или учишься писать код. Насколько хорошо ты пишешь код? Ответить на этот вопрос сейчас и после прочтения статьи. А затем скажи в комментариях, насколько ты продвинулся в понимании чистоты кода.

Сегодня сложно найти человека, который бы взялся за написание кода какого-то проекта и не использовал библиотеки. Это абсолютно нормально, ведь библиотеки позволяют сократить время разработки, упростить решение задач, а также не изобретать каждый раз велосипед.

Но замечали ли вы, что использование чужого кода в вашем проекте засоряет его? Если быть точнее, то усложняет его чтение.

Почему так происходит? На это есть ряд причин:

  • у вашего кода есть свой стиль, который не совпадает со стилем стороннего кода;
  • разработчики библиотек стараются сделать универсальный код, который решает задачи для любых проектов. По этой причине код библиотек часто перенасыщен различными аргументами или длинными вложениями;
  • в библиотеке используется другое пространство имен, которое не сочетается с вашим;
  • классы предоставляемые библиотекой содержат слишком много методов, которые нужно вызвать, чтобы решить лишь одну задачу в вашем проекте.

Все это создаёт размытый код. Про размытие можно узнать в этой статье:

Что такое граница?

Под границей подразумевается область, где ваш проект пересекается с библиотеками. Лучше разобрать это на примере изображения.

Показано насколько библиотеки интегрированы в ваш проект (образный проект)
Показано насколько библиотеки интегрированы в ваш проект (образный проект)

Ваш проект на изображении - это зеленый круг, который частично взял код из каждой библиотеки. Чем больше кода от библиотек в вашем проекте, тем уже границы вашего проекта.

А нужно ли защищать границы вашего проекта? Естественно.

Пример

Давайте приведем простой пример: представьте, что ваш проект - это страна, у которой есть свои границы. Каждый раз, когда её правительству нужно что-то сделать (получить), то они договариваются с соседями и взамен на помощь сдвигают свои границы внутрь, тем самым сужая их.

Правительство на тактическом уровне получает какую-то моментную пользу от таких решений. Но каждый раз, получая что-то от соседей и взамен сужая свои границы, у правительства не остается влияния на соседей.

Происходит это потому, что нельзя правительству этой страны указывать, что должны делать люди на землях, которые им когда-то принадлежали.

В результате такой политики правительство становится марионеточным и не имеет возможности принимать стратегические решения, т.к. нет пространства для маневра.

Вы должны защищать свои границы также, как государства защищают свои.

  1. К чему нужно стремиться?

В статье про уровни абстракции:

Я рассказывал о том, как влияет единый уровень абстракции кода на его читаемость.

Как только границы вашего проекта сдвигаются, то в ваш код попадает мусор. Происходит размытие, которое ухудшает чтение кода. Стремиться нужно к тому, чтобы ваш код всегда имел один уровень абстракции.

Пример

Допустим у нас есть некая таблица, в которую постоянно добавляются новые записи и нам необходимо, каждый раз, выводить из неё в консоль последние три записи.

Представим данные таблицы сразу в формате выгруженном в словарь (ассоциативный массив).

Данные таблицы
Данные таблицы

Как вывести их в консоль в формате таблицы? Сразу в голове начинает проявляться картина по созданию велосипеда через костыли? Не стоит этого делать. Для работы с данными есть хорошая библиотека Pandas.

У неё есть прекрасный класс, который называется DataFrame. Если подавать в него словарь, то в результате он будет выводить его в виде таблицы. Вот стандартный код:

Код, который выводит весь словарь в виде таблицы
Код, который выводит весь словарь в виде таблицы

Результат работы такого кода будет следующим.

Результат
Результат

Но, как мы сказали ранее, в постановке нашей задачи стоит вопрос о выводе лишь последних трёх записей, а не всей таблицы.

Тогда мы идем в документацию и смотрим, какие есть методы.

  • head(): возвращает первые несколько строк из DataFrame;
  • tail(): возвращает последние несколько строк из DataFrame;
  • info(): выводит информацию о DataFrame, включая типы данных и количество ненулевых значений;
  • describe(): возвращает статистическую сводку для числовых столбцов DataFrame;
  • shape: возвращает размерность DataFrame в виде кортежа (количество строк, количество столбцов);
  • columns: возвращает список названий столбцов DataFrame;
  • index: возвращает индекс (метки строк) DataFrame;
  • loc[]: позволяет выбирать данные по меткам строк и столбцов;
  • iloc[]: позволяет выбирать данные по целочисленным индексам строк и столбцов;
  • drop(): удаляет указанные строки или столбцы из DataFrame;
  • sort_values(): сортирует DataFrame по значениям указанного столбца;
  • groupby(): группирует данные по указанному столбцу или набору столбцов;
  • merge(): объединяет два DataFrame по общим столбцам или индексам;
  • pivot_table(): Создает сводную таблицу на основе данных DataFrame.

Ого, как много всего… Нам столько не нужно в проекте. Фактически нас интересует только один метод tail и все.

Мы можем в выводе указать данный метод и получить результат.

Вывод последних трех записей
Вывод последних трех записей

Мы получили то, что хотели. Но задумайтесь, ведь теперь каждый раз, когда вы хотите в вашем проекте вывести последние три строки из какой-либо таблицы, вам нужно писать это:

df = pandas.DataFrame(data)

print(df.tail(3))

Этот чужеродный код будет выглядеть ужасно в вашем проекте. А что если в библиотеке произойдут какие-то изменения? Вы будете ходить по всему коду вашего проекта и вносить изменения в эти строки.

Напомню, основная проблема заключается в том, что этот код захватывает границы вашего проекта, а должно быть наоборот.

В примере с государственной границей можно было бы сказать, что вам нужен пограничный пункт, который будет пропускать только то, что разрешено.

Пограничные пункты в вашем проекте

В вашем проекте можно легко создать пограничный пункт, который будет пропускать в код только то, что действительно нужно.

Жесткое ограничение на границе проекта позволяет создавать чистый код
Жесткое ограничение на границе проекта позволяет создавать чистый код

Вспомните список методов, который мы рассматривали выше. Зачем в нашем проекте позволять программистам иметь доступ к таким методам:

  • drop(): удаляет указанные строки или столбцы из DataFrame;
  • sort_values(): сортирует DataFrame по значениям указанного столбца;
  • head(): возвращает первые несколько строк из DataFrame;
  • groupby(): группирует данные по указанному столбцу или набору столбцов.

Если один из участников проекта, решит использовать такой метод, то могут ли из-за этого появиться проблемы в решении нашей задачи?

Кончено! Что-то удалить, отсортировать, сгруппировать или вывести строки из начала таблицы - это все приведет к большим проблемам и долгим поискам ошибки.

Поэтому нельзя допустить, чтобы у программистов был доступ к не нужным функциям. Грубо говоря - это как таможня, которая разрешает провозить определенные товары, а на все остальные вводится запрет и они остаются за границей.

Какая техника позволяет это реализовать?

Ответ прост: обертывание. Вы просто создаете отдельный файл, в нем создаете свой собственный класс, который будет оберткой (пограничным пунктом), а в нем определяешь только те методы, которые должны быть доступны.

В нашем случае нужно создать класс, который будет выводить последние три строки таблицы. Так его и назовем. Файл назовем также, как и класс.

Пишем код:

Наш пограничный класс
Наш пограничный класс

Теперь импортируем наш класс в файл проекта, где необходимо получить результат последних трех строк.

Код с пограничным классом
Код с пограничным классом

Обратите внимание насколько чистым стал код вашего проекта. Его больше не загрязняет код сторонней библиотеки. Вы даже не знаете, что используется какая-то библиотека.

Теперь есть специальный класс, который имеет только один метод выполняющий ровно то, что необходимо в проекте.

И если вдруг что-то изменится в библиотеке, то вы можете изменять это в одном классе, и не бегать по всему проекту в поисках стороннего кода.

Границы проекта не нарушены, таможня свое дело сделал. 🙂

Выводы

Если вы только начинаете писать код, то возможно вы думаете, что это все лишнее, т.к. главное чтобы год работал. Но это не так.

Вы пишите код один раз, а читаете его много раз, поэтому намного важнее делать все, чтобы он был удобным для чтения, а не просто работал без ошибок.

Умение писать чистый код - это первые признаки профессионализма. Стремитесь к совершенству и читайте статьи на данном канале. 🙂

Подписывайтесь на канал, чтобы быть в курсе всего, что происходит в IT.