Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
Сопротивляйтесь добавлению в проект нов…

Сопротивляйтесь добавлению в проект новых библиотек

15 Янв 2016

Итак, вам понадобилось реализовать в проекте функциональность X. Теоретики разработки программного обеспечения в этот момент говорят, что для этого нужно взять уже существующую библиотеку Y и использовать её для реализации необходимых вам вещей. Собственно, это классический подход в разработке программного обеспечения - повторное использование своих или чужих наработок (сторонних библиотек). И именно этим путём движется большинство программистов.

0369_Avoid_adding_a_newnlibrary_ru/image1.png

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

Я рекомендую всячески сопротивляться добавлению в проект каждой новой библиотеки. Но прошу понять меня правильно. Я вовсе не говорю, что не надо использовать библиотеки и писать всё самостоятельно. Это просто-напросто глупо. Однако, часто новая библиотека добавляется в проект по прихоти одного разработчика, с целью использовать в ней какую-то маленькую "фитюльку". Добавить новую библиотеку не сложно. Вот только потом всей команде много лет придётся нести груз её поддержки.

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

  • Добавление новых библиотек быстро увеличивает размер проекта. В нашу эпоху быстрого интернета и больших SSD дисков это не является существенно проблемой. Однако, когда проект начинает скачиваться из системы контроля версий не за 1 минуту, а за 10, это уже неприятно.
  • Даже если вы используете 1% от возможностей библиотеки, как правило в проект она будет включена целиком. В результате, если библиотеки используется в виде готовых модулей (например, DLL), то очень быстро растёт размер дистрибутива. Если вы используете библиотеки в виде исходного кода, то существенно увеличивается время компиляции.
  • Усложняется инфраструктура, связанная с компиляцией проекта. Некоторым библиотекам требуются дополнительные компоненты. Простой пример: для сборки требуется наличие Python. В результате через некоторое время для сборки проекта нужно в начале вырастить на компьютере целый сад вспомогательных программ. Возрастает вероятность, что где-то что-то перестанет работать. Объяснить это сложно, это надо прочувствовать. В больших проектах постоянно "отваливается" то одно то другое и нужно постоянно прилагать усилие чтобы всё работало и компилировалось.
  • Если вы заботитесь об уязвимостях, вы должны регулярно обновлять сторонние библиотеки. Злоумышленникам выгодно изучать код библиотек с целью поиска уязвимостей. Во-первых, многие библиотеки открыты, а во-вторых, найдя дыру в одной из библиотек можно получить отмычку сразу ко многим приложениям, где эта библиотека используется.
  • У вас будут проблемы при переходе на новую версию компилятора. Обязательно будет несколько библиотек, которые не будут торопиться адаптироваться под новый компилятор. И вы будете вынуждены ждать или самим вносить какие-то правки в библиотеки.
  • У вас будут проблемы при переходе на другой компилятор. Например, вы используете Visual C++, а хотите использовать Intel C++. Обязательно найдется пара библиотек, с которыми что-то не заладится.
  • У вас будут проблемы при переходе на другую платформу. Не обязательно даже на "сильно другую платформу". Достаточно захотеть превратить Win32 приложение в Win64. У вас будут все те-же проблемы. Несколько библиотек к этому окажутся не готовы и будет непонятно, что с ними делать. Особенно неприятна ситуация, когда библиотека заброшена и более не развивается.
  • Рано или поздно, если вы используете множество Си-библиотек, где типы не лежат в namespace, у вас начинают пересекаться имена. Это приводит к ошибкам компиляции или к скрытым ошибкам. Например, начинает использоваться константа не из того enum, из которого вы планировали.
  • Если в проекте используется много библиотек, добавление ещё одной не выглядит чем-то вредным. Можно провести аналогию с теорией разбитых окон. В результате разрастание проекта приобретает неконтролируемый характер.
  • Есть масса других негативных моментов, о которых я не помню и не знаю. Но в любом случае дополнительные библиотеки очень быстро увеличивают сложность поддержки проекта. Это сложность может проявляться в самых неожиданных местах.

Ещё раз подчеркну. Я не призываю вас отказаться от использования сторонних библиотек. Если в программе вам понадобилось работать с изображениями в формате PNG, то вам надо взять библиотеку LibPNG и не изобретать велосипед.

Но даже работая с PNG надо остановиться и подумать. А нужна ли библиотека? Какие операции нужно выполнять с изображениями? Быть может, если вся задача сводится к тому, чтобы сохранить какое-то изображение в *.png - файл, можно обойтись системными функциями. Например, если у вас Windows приложение, то вам поможет WIC. А если вы уже используете библиотеку MFC, та вообще не надо усложнять код, ведь есть класс CImagе (см. обсуждение на сайте StackOverflow). Минус одна библиотека - отлично!

Приведу пример из собственной практики. В процессе разработки анализатора PVS-Studio, в паре диагностик потребовалось применять простые регулярные выражения. Вообще, я убеждён, что регулярным выражениям не место в статическом анализе. Это крайне неэффективный подход. Я даже писал статью на эту тему. Однако иногда, в какой-то строке нужно бывает что-то найти с помощью регулярного выражения.

Можно было-бы "прикрутить" какую-то из существующих библиотек. Было понятно, что все они будут избыточны, но ведь регулярные выражения все равно нужны и нужно было принять какой-то решение.

Совершенно случайно, именно в тот момент я читал книгу "Beautiful Code" (ISBN 9780596510046). Эта книга о простых и изящных решениях. И в ней я повстречал крайне простую реализацию регулярных выражений. Буквально несколько десятков строк. И всё!

Я взял из книги эту реализацию и начал использовать в PVS-Studio. И знаете, что? До сих пор возможностей этой реализации нам хватает. Какие-то сложные регулярные выражения нам просто не нужны.

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

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

Возможно читателям будет интересно узнать, что же это за такой код для поиска по регулярным выражениям. Перепечатаю его из книги. Посмотрите, как элегантно. Это код был мной немого изменён при интеграции в PVS-Studio, но его суть не изменилась. Итак, код из книги:

// Формат регулярного выражения.
// c     Соответсвует любой букве "с"
// .(точка)  Соответсвует любому одному символу
// ^     Соответсвует началу входящей строки
// $     Соответствует концу входящей строки
// *     Соответствует появлению предыдущего символа от нуля до
//       нескольких раз

int matchhere(char *regexp, char *text);
int matchstar(int c, char *regexp, char *text);

// match: поиск соответствий регулярному выражению по всему тексту
int match(char *regexp, char *text)
{
  if (regexp[0] == '^')
    return matchhere(regexp+1, text);
  do { /* нужно посмотреть даже пустую строку */
   if (matchhere(regexp, text))
     return 1;
  } while (*text++ != '\0');
  return 0;
}

// matchhere: поиск соответствий регулярному выражению в начале текста
int matchhere(char *regexp, char *text)
{
   if (regexp[0] == '\0')
     return 1;
   if (regexp[1] == '*')
     return matchstar(regexp[0], regexp+2, text);

   if (regexp[0] == '$' && regexp[1] == '\0')
     return *text == '\0';
   if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
     return matchhere(regexp+1, text+1);
   return 0;
}

// matchstar: поиск регулярного выражения вида с* с начала текста
int matchstar(int c, char *regexp, char *text)
{
  do {   /* символ * соответствует нулю или
            большему количеству появлений */
    if (matchhere(regexp, text))
      return 1;
  } while (*text != '\0' && (*text++ == c || c == '.'));
  return 0;
}

Итак, мой совет

Сопротивляйтесь добавлению в проект новых библиотек. Добавлять следует только когда, когда очевидно, что без библиотеки не обойтись.

Вот некоторые возможные манёвры:

  • Быть может нужную функциональность уже предоставляет API вашей системы или одна из уже используемых библиотек. Исследуйте этот вопрос.
  • Если вы планируете использовать совсем маленький кусочек функциональности из библиотеки, то есть смысл реализовать его самостоятельно. Аргумент "лучше подключить библиотеку, вдруг потом ещё что-то понадобится" никуда не годится. Почти всегда из этой библиотеки в будущем больше ничего использоваться не будет. Программисты слишком тяготеют к универсальности, которая на самом деле не нужна.
  • Если для решения задачи есть несколько библиотек, то выбирайте самую простую, которая удовлетворяет требованиям. Как я писал выше, гоните прочь мысли "на всякий случай взять библиотеку покруче".
  • Прежде чем начать добавлять библиотеку, просто подождите и подумайте. Попейте чаю, отвлекитесь, обсудите задачу с коллегами. Возможно в процессе выяснится, что можно решить задачу совсем иным путём, не прибегая к помощи сторонних библиотек.

P.S. Многим рассказанное здесь придется не по душе. Например, то что я рекомендую использовать не переносимую универсальную библиотеку, а допустим WinAPI. На это будут возражения, основанные на том, что тем самым мы привязываем проект к одной операционной системе. И потом будет очень сложно сделать программу переносимой. Я с этим не согласен. Часто идея "потом перенесем на другу операционную систему" живет только в голове разработчика. На самом деле такая задача вообще может быть никогда не поставлена руководством. Или проект "загнётся" из-за излишней сложности и универсальности, ещё до момента популярности и необходимости портирования. Плюс не забывайте пункт (7) в списке проблем, приведенный выше.

Популярные статьи по теме
Как и почему статические анализаторы борются с ложными срабатываниями

Дата: 20 Мар 2017

Автор: Андрей Карпов

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…
Бесплатный PVS-Studio для тех, кто развивает открытые проекты

Дата: 22 Дек 2018

Автор: Андрей Карпов

В канун празднования нового 2019 года команда PVS-Studio решила сделать приятный подарок всем контрибьюторам open-source проектов, хостящихся на GitHub, GitLab или Bitbucket. Им предоставляется возмо…
Зло живёт в функциях сравнения

Дата: 19 Май 2017

Автор: Андрей Карпов

Возможно, читатели помнят мою статью под названием "Эффект последней строки". В ней идёт речь о замеченной мной закономерности: ошибка чаще всего допускается в последней строке однотипных блоков текс…
PVS-Studio для Java

Дата: 17 Янв 2019

Автор: Андрей Карпов

В седьмой версии статического анализатора PVS-Studio мы добавили поддержку языка Java. Пришло время немного рассказать, как мы начинали делать поддержку языка Java, что у нас получилось и какие дальн…
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

Автор: Андрей Карпов

Вы угадали, ответ - "42". Здесь приводится 42 рекомендации по программированию, которые помогут избежать множества ошибок, сэкономить время и нервы. Автором рекомендаций выступает Андрей Карпов - тех…
Любите статический анализ кода!

Дата: 16 Окт 2017

Автор: Андрей Карпов

Я в шоке от возможностей статического анализа кода, хотя сам участвую в разработке инструмента PVS-Studio. На днях я был искренне удивлён тому, что анализатор оказался умнее и внимательнее меня.
Статический анализ как часть процесса разработки Unreal Engine

Дата: 27 Июн 2017

Автор: Андрей Карпов

Проект Unreal Engine развивается - добавляется новый код и изменятся уже написанный. Неизбежное следствие развития проекта - появление в коде новых ошибок, которые желательно выявлять как можно раньш…
Эффект последней строки

Дата: 31 Май 2014

Автор: Андрей Карпов

Я изучил множество ошибок, возникающих в результате копирования кода. И утверждаю, что чаще всего ошибки допускают в последнем фрагменте однотипного кода. Ранее я не встречал в книгах описания этого …
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

Автор: Андрей Карпов

После большой статьи про проверку операционной системы Tizen мне было задано много вопросов о проценте ложных срабатываний и о плотности ошибок (сколько ошибок PVS-Studio выявляет на 1000 строк кода)…
Как PVS-Studio оказался внимательнее, чем три с половиной программиста

Дата: 22 Окт 2018

Автор: Андрей Карпов

PVS-Studio, как и другие статические анализаторы кода, часто выдаёт ложные срабатывания. Но не стоит спешить считать странные срабатывания ложными. Это короткая история о том, как PVS-Studio вновь ок…

Комментарии (0)

Следующие комментарии

На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять