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

Собственно, это классический подход в разработке программного обеспечения — повторное использование своих или чужих наработок (сторонних библиотек). И именно этим путём движется большинство программистов.

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

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

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

Ещё раз подчеркну. Я не призываю вас отказаться от использования сторонних библиотек. Если в программе вам понадобилось работать с изображениями в формате 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;
}



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

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

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

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


  1. Atakua
    15.01.2016 12:26
    +14

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

    От себя добавлю ещё одну проблему. Она возникает в больших и серьёзных компаниях, когда существенен легальный статус выпускаемого продукта: возрастание затрат времени на анализ лицензий входящих сторонних библиотек. Особенно, если их лицензии меняются по ходу дела.
    Например, в прошлом году библиотека softfloat перешла с «самодельного» соглашение на BSD. Во многих программных симуляторах требуется моделировать инструкции над числами с плавающей запятой в формате IEEE 754, и многие из них используют именно для этого именно softfloat. И иногда код ещё и модифицируется (например, включается поддержка 82-битных чисел).


    1. fshp
      15.01.2016 13:56
      +2

      Вы что, из мастера/транка библиотеки тащите?


      1. Ogra
        15.01.2016 14:06
        +2

        Тащишь из мастера/транка — огребаешь от обновлений, тащишь определенные версии — огребаешь проблемы с безопасностью.


        1. fshp
          15.01.2016 14:50
          +4

          огребаешь проблемы с безопасностью

          Если вы знаете о конкретной проблеме, тогда можно перейти на новый релиз, предварительно прочитав чейнжлог. Или исправить ошибку силами своей команды.
          Если о проблеме вы не знаете, но тараканы в голове не дают вам уснуть, шепчя в ухо постоянно «безопасность, безопасность!», то как вы можете быть уверены, что новая версия не откроет кучу новых дырок?


          1. Ogra
            15.01.2016 15:44

            Если вы знаете о конкретной проблеме

            Да, я о том и говорю, что подключив библиотеку крайне желательно следить за ней: либо за сменой API, если подключаете master/trunk, либо за обновлениями безопасности, если подключаете какую-то версию.


  1. Hydro
    15.01.2016 12:29
    +8

    Провокационно-холиварный пост, хотя в общем и целом согласен, правда есть и другая крайность:
    так появляются свои, проприетарные библиотеки/фреймворки: сделали что-то маленькое и нужное, вынесли в отдельный модуль (хорошо бы переиспользовать потом где-нибудь, неправда- ли?), через месяц еще туда запихали «нужного», потом еще, потом еще.


    1. XAHOK
      19.01.2016 19:24

      Я использую простое решение: разбейте этот разожравшийся мего-проект на небольшие узко специализированные проекты в одном солюшене. Все под рукой, неплохо структурировано и кучу лишнего за собой не тянет. Как правило, и зависимостей между такими библиотеками нет. Да и собираться он будет 1 раз в N единиц времени, что не сильно критично даже при большом количестве проектов.

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


  1. tuupic
    15.01.2016 13:10
    -6

    Windows-only пост, имхо. Дополнительная библиотека — это дополнительная строка в debian/control и pkgname.spec


    1. shai_hulud
      15.01.2016 13:17
      +30

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


      1. tuupic
        15.01.2016 13:20
        -12

        Не надо мне рассказывать про поддержание внешних библиотек в проекте. Моя работа отчасти с этим связана. И в 90% всё его поддержание заключается в добавление разовой зависимости.


        1. shai_hulud
          15.01.2016 13:32
          +17

          т.е. на десять пунктов из статьи у вас один аргумент: надо добавить зависимость в пакетный менеджер.

          Но в чудесном мире разработки иногда авторы пакета:
          а) поворачивают реки вспять и переписывают основной API под новые веянья
          б) отказываются править баги
          в) отказываются обновлять зависимости
          г) обновляют свои зависимости до бета версий
          д) умирают
          е) меняют лицензию (лучше уж пусть умирают)


          1. tuupic
            15.01.2016 13:40
            -12

            т.е. на десять пунктов из статьи у вас один аргумент: надо добавить зависимость в пакетный менеджер.

            Просто из 10 пунктов только 3 последних актуальны для linux систем. Остальное неактуально, при наличии библиотеки в стандартном репозитории ОС.
            Судя по вашему перечислению, вы не очень хорошо знаете «экосистему», так как что CentOS, что Debian не обновляют пакеты в рамках одного релиза. Поэтому смены API, лицензий и т.д. опять же не страшны. Остаётся толлько отсутствие некоторых исправлений. Которые попадают под 10%


            1. shai_hulud
              15.01.2016 13:57
              +7

              разработка != сборка из сорцов


            1. poxu
              15.01.2016 14:00
              +2

              Первые 2 пункта для линукса менее актуальны. А все остальные только в путь. И усложнение инфраструктуры и уязвимости и версии компиляторов и платформ.


              1. tuupic
                15.01.2016 14:03
                -5

                Уязвимости библиотек в офф репозитории — забота их мэнтейнеров. И у них следить за этим получается лучше :)


                1. poxu
                  15.01.2016 14:09
                  +1

                  Так и есть, но они всё равно не справляются. Поэтому лучше просто не использовать библиотеку, если это возможно.


                  1. tuupic
                    15.01.2016 14:12
                    +1

                    В linux, что libpng, что libc — одинаково внешние зависимости. Писать без libc C++ немного тяжеловато будет :)


                    1. poxu
                      15.01.2016 14:12
                      +4

                      Ну автор примерно так и написал. В частности про libpng. Если не обойтись — надо использовать.


                1. BelBES
                  15.01.2016 20:14
                  +5

                  Уязвимости и баги в вашем ПО, вызванные зависимостями — это проблема разработчиков. И неожидданно может оказаться, что половину внешних библиотек пришлось фиксить самостоятельно, и теперь прокет собирается только с кастомными сборками внешних библиотек, и либо в проекте растет размер папки аля 3rdparty, либо приходится указывать, откуда брать правильные версии библиотек (которые в свою очередь могут начать конфликтовать с чем-нибудь на ПК пользователя). А бывают еще замечательные зависимости типа gstreamer'а или ffmpeg'а у которых API ломают чуть ли не в минорных апдейтах.
                  А не дай бог еще весь проект — это какое-то критичное ПО, подлежащее к сертификации по какой-нибудь MISRA, то с кучей депендеси можно вешаться.

                  Т.ч. внешние зависимости даже в linux — это далеко не «добавить одну строчку в debian/control и pkgname.spec и радоваться жизни», все как всегда умирает на сопровождении. И иногда проще написать приватный фреймворк, с полностью контролируемым кодом, чем тягать зависимости из внешних библиотек.


              1. reji
                15.01.2016 23:48

                Ваши слова да каждому разработчику в сердце! Особенно ребятам из salt, из OpenStack из злободневных.
                Причем проблемы с обратной совместимостью появляются даже в таких «серьёзных и проверенных временем» проектах, как mongodb(привет совместимости аутентификации в различных версиях).


            1. erlyvideo
              16.01.2016 10:38
              -2

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


              1. tuupic
                16.01.2016 18:30

                А зачем туда попадать? ПО замечательно распространяется через сторонние репозитории


                1. erlyvideo
                  16.01.2016 21:38

                  тогда не надо фантазировать насчёт несменяемости библиотек.


                  1. tuupic
                    17.01.2016 05:45
                    -2

                    Библиотеки-то как жили в офф репе, так и остались. Со своими стабильными версиями. А в стороннем репозитории только сам пакет с распространяемым ПО.


                    1. erlyvideo
                      17.01.2016 10:52
                      +2

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

                      Нормальная ситуация — несколько лет отставания в обновлении.


                      1. 0xd34df00d
                        17.01.2016 21:34

                        Почему? Пересобрал пакет, и всё. Если ломающих изменений в API не было, то и проблем никаких.


                    1. Gendalph
                      17.01.2016 15:17

                      Специально для вас: habrahabr.ru/company/pvs-studio/blog/275159/#comment_8741329
                      Вопрос: насколько отстаёт стандартная репа RHEL/CentOS от официального стабильного релиза?


                      1. tuupic
                        17.01.2016 16:42
                        +1

                        От стабильного релиза чего? Вы хотите юзать, например, openssl последней версии? Флаг в руки, только зачем? Вам шашечки или функциональность?
                        Если нужна непременно какая особенная версия, и этой версии нету в репах поддержимаевого дистрибутива — не стоит её использовать и стоит поискать другой вэй.
                        Решение об использовании библиотеки выносится с учётом того, а есть ли она в поддерживаемых нашим ПО дистрибутивах(проблемы индейцев на arch, gentoo и т.д. не интересны). Если она есть и её версия подходит(а такое чаще всего), то никаких аргументов против нету.
                        Не спорю, проблемы могут быть, например с namespace, была один раз c mysql и gnutls(точнее в зависимости у gnutls — trousers: http://sourceforge.net/p/trousers/trousers/ci/7d207231355a5702cbdcf24628e8c1e2e3722593/

                        Но как уже писали и ниже, как я писал выше, в контексте C/C++ linux разработки актуальны только последние 3 из 10.

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

                        p.s. проблемы aur — это проблемы arch, а не разработчика ПО, если этот разработчик не брал на себя иных обязательств.


                        1. Gendalph
                          17.01.2016 16:49

                          В ваших кейсах — может быть.
                          Но я повторюсь, бывают случаи когда по тем или иным причинам собрать какую-то версию либы/пакета бывает сложно. И речь не только об Arch, у нас было такое и на старых Ubuntu.
                          Поэтому если пакет тянет за собой тучу зависимостей — это сулит геморрой при обновлении дистра и лично я стараюсь такого софта избегать.
                          Яркий пример — virt-manager. Может это и отличный инструмент, но просто потому что он за собой тянет еще полтора десятка пакетов которые реализуют ненужные мне функции, я не стану его ставить.


                1. Gendalph
                  16.01.2016 23:00
                  +2

                  Великолепно.
                  Вам рассказать как я собирал один SIP-клиент из AUR'а?
                  Затык был один: какая-то сторонняя библиотека обновилась, а старую версию выпилили с сайта. Смешно? Мне нет.


                  1. Gendalph
                    17.01.2016 02:27

                    Ой, а я тут еще вспомнил про сервер с FreeBSD 7.x, на который не ставится rsnapshot.
                    rsnapshot. КАРЛ! Модулей в CPAN'е нету. Порты из CVS нельзя обновить — нету их там больше. Так и гуглю до сих пор, старые версии либ…


                    1. erlyvideo
                      17.01.2016 10:53

                      почему вы его просто не переустановите? 7-ка это же что-то несусветно древнее.


                      1. Gendalph
                        17.01.2016 15:14

                        Я бы не против, но права не имею.


          1. 0xd34df00d
            17.01.2016 21:33
            +1

            Форкаете и пилите дальше, какие проблемы?

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


        1. poxu
          15.01.2016 13:33
          +2

          На всякий случай перескажу содержимое статьи.
          Проблемы появляются когда:
          1. Пытаешься сменить версию компилятора
          2. Пытаешься сменить компилятор
          3. Пытаешься сменить платформу
          4. Начинаются коллизии имён типов


          1. tuupic
            15.01.2016 13:50

            1,2. В рамках одного релиза debian/centos один компилятор является штатным. И все бинарные пакеты в репах уже им собраны.
            3. Если пакет в репозитории есть для 32 битной архитектуры, то и для 64 бита тоже. Проблемы могут быть с arm, но большая часть всё же там есть, да мы arm не поддерживаем.
            4. Вот это было 1 раз.

            Повторюсь, для linux проектов актуальны только 3 пункта из 10. Сужу по собственном опыту.

            Распухание проекта, проблемы со сборкой этих зависимостей и т.д. — неактуально


            1. AEP
              15.01.2016 13:59
              +2

              Более того, любые добавленные в проект внешние зависимости, если ваше приложение таки попадет в официальные репозитории, будут безжалостно удалены мейнтейнерами (согласно правилам дистрибутива) и заменены на системные версии.


              1. poxu
                15.01.2016 14:02
                +1

                Тут-то ваше приложение и перестанет работать.


                1. AEP
                  15.01.2016 14:08
                  +1

                  Не перестанет. Если оно от такой замены ломается, оно просто не будет добавлено. Если оно сломается от обновления, то будет удалено из дистрибутива (как xmms, привязанный к GTK1) — но это никогда не происходит в пределах стабильной ветки дистрибутива. Поэтому на линукс-разработчиках всегда лежит обязанность поддерживать совместимость со всеми возможными версиями зависимостей, в т.ч. с еще не выпущенными.


                  1. poxu
                    15.01.2016 14:11

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


                    1. AEP
                      15.01.2016 14:19

                      С этим согласен.


                    1. Eklykti
                      15.01.2016 19:09

                      А чтоб минимизировать время адаптации под новые версии зависимостей, надо вместо qt и gtk писать на голой xlib


            1. poxu
              15.01.2016 14:07

              Про архитектуры — допустим. Наверное время, когда авторы переводили свои проекты с 32 на 64 и ловили эпические баги — уже прошло. Но собирать библиотеки самому всё равно придётся, смена компилятора — всё равно боль, попытка собрать код под FreeBSD — всё равно может не увенчаться успехом.


      1. 0xd34df00d
        17.01.2016 21:33
        +1

        Какие пакетные менеджеры работают отлично под Windows, и сравнится ли набор доступных там библиотек с таковым в каком-нибудь Debian или Gentoo с оверлеями?

        На память только msys2 приходит, то он не сказать чтоб распространён, насколько я скудно могу судить.


    1. unixod
      15.01.2016 13:35
      +3

      Добрый день!

      В посте речь идет про разработку а не про деплой/использование конечными пользователями. Моменты описанные в статье актуальны для любого кроссплатформенного проекта.


    1. Gendalph
      16.01.2016 22:56

      Я вчера попытался поставить у себя virt-manager на Arch'е.
      Мне предложило утянуть 28 зависимостей.
      Я посмотрел, подумал и нажал Ctrl+C.


  1. ov7a
    15.01.2016 13:36
    +9

    > Например, если у вас Windows приложение, то вам поможет WIC. А если вы уже используете библиотеку MFC, та вообще не надо усложнять код, ведь есть класс CImagе (см. обсуждение на сайте StackOverflow). Минус одна библиотека — отлично!

    Отлично! Теперь-то, разумеется, я не наступлю на грабли из пунктов 7, 6, 1, 2, 4!

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


  1. BenderRodriguez
    15.01.2016 13:43
    +2

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

    Это конечно разумно. Но я бы продолжил рекомендацию, Open Source by Default:

    Всегда ищите маленькие атомарные библиотеки для реализации какого-либо повторяющегося функционала. Если не найдете — по мере возможностей создайте такую и выложите в Open Source.

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

    Я iOS-разработчик, приведу пример хорошей и плохой библиотеки:
    1) github.com/mxcl/UIImageWithColor
    пусть это всего несколько строчек, но я считаю разумным вынести это в дополнительный модуль, а не копипастить из раза в раз.

    2) Three20 и в меньшей степени, но Nimbus
    github.com/jverkoey/nimbus
    Тащить в проект 10 контролов ради одного? И скорее всего они будут развиваться только параллельно, хотя отдельно один их них мог заглохнуть, а один стать очень популярным и получить внимание разработчиков, которые не обращают внимание на все-в-одном.

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

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


    1. Pilat
      16.01.2016 15:49
      +1

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


      1. 0xd34df00d
        17.01.2016 21:35
        +2

        Попробовал. Не изменилось.


  1. SerCe
    15.01.2016 14:54
    +13

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

    1) VCS для сорцев, а не для бинарников, все бинарники хранятся в бинарном репозитории.
    2) Время компиляции увеличивается несущественно
    3) Не актуально для 95% библиотек, билд системы полностью решают эту проблему
    4) Библиотеки хотя бы исправляют, а у вас "security through obscurity", для настоящего злоумышленника — не помеха
    5) Binary compatibility
    6) Binary compatibility
    7) JVM везде JVM
    8) Ни разу не встречал подобную проблему в языках с явными импортами и корректной статической типизацией
    9, 10) Отвечу одно — библиотека — 150+ коммитов исправлений, накопленный опыт, ваш велосипед — 1 коммит…

    Поэтому статья актуальна не для хаба «разработка», а для «c++»

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


    1. andrewsch
      15.01.2016 16:07
      +2

      Хотя в Java и проще, но все равно большое количество сторонних библиотек зачастую приводит к проблемам.

      Сам сталкивался и со сменой лицензий, и прекращением поддержки, и (вдруг, при попытке обновления библиотеки) несовместимости зависимостей с другими библиотеками. По жтим причинам некоторые тяжеловесные сторонние библиотеки нам пришлось вынести в независимые процессы — чтобы избежать конфликтов зависимостей.


    1. erlyvideo
      16.01.2016 10:40
      -5

      ахахаха!

      Я охотно верю что в голове у среднего джавадевелопера такая же каша и поэтому типичный джавопроект — это по одной библиотеке на одну строчку существенной логики.

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


      1. SerCe
        16.01.2016 10:44
        +1

        А может аргументированно попробуете ответить?


        1. erlyvideo
          16.01.2016 10:52
          -3

          Все советы, которые давал автор абсолютно верны для любого языка программирования.

          API у библиотек меняется, в них находят уязвимости. Одну и ту же библиотеку могут втянуть разные импортированные библиотеки под разными версиями. Джава от этого не защитит.


          1. SerCe
            16.01.2016 10:58
            +1

            абсолютно верны для любого языка программирования

            Пролистайте чуть выше, я там перечислил почему не верны, прямо по пунктам

            в них находят уязвимости

            И исправляют их, а в вашем коде никто не исправляет не баги, не уязвимости

            под разными версиями

            Да, я выше и написал, трейдоф, однако правильные билд-системы предоставляют мощнейшие тулы чтобы решить эту проблему


            1. erlyvideo
              16.01.2016 21:43
              -1

              ну что вы фантазируете? =) Как вам билд-система решит проблему, когда библиотека A требует C версии 1.5, а библиотека B требует C версии 2.0!

              И я сейчас говорю не про ту легкую ситуацию, когда можно фиксировать выбор, скажем C=1.7 и удовлетворить обе библиотеки, а именно про жесткую и нерешаемую зависимость.

              Рантайм то один и адресное пространство в нём одно.


              1. SerCe
                16.01.2016 23:08
                +1

                Отлично, со всеми пунктами разобрались, остался последний, «транзитивные зависимости» (заметим, что ее автор даже не упомянул, хотя это как раз и есть может стать проблемой). Билд система вам, конечно, не решит эту проблему, однако просигнализирует и предложит попытку решить «ту легкую ситуацию».

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


                1. erlyvideo
                  17.01.2016 10:56
                  -2

                  это вы — инженер, которому платят за работу. Я владелец бизнеса, которому потом разгребать последствия ковбойства в стиле «а, втащим ещё одну тулзу, она разрулит конфликты между предыдущими двумя втащенными либами».

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


                  1. SerCe
                    17.01.2016 11:27
                    +1

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


                    1. erlyvideo
                      17.01.2016 12:31
                      -3

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


                      1. SerCe
                        17.01.2016 12:36

                        Можно поподробнее, с цитатами вместо голословных утверждений?


    1. scrutari
      16.01.2016 11:17
      +1

      Вы, в целом, правы, но есть проекты, например, на C и C++, и там нет бинарных репозиториев (например, в Cmake 3.3+ нет поддержки управления зависимостями напрямую; можно, конечно, что-то придумать самому, но такой красоты как с Maven нет). Как правило, даже такого понятия, как управляемая зависимость нет.


    1. Kluyg
      20.01.2016 02:16

      Проблемы начинаются когда вы используете библеотеку А и Б, потом нужно добавить библиотеку С, но внезапно она тоже использует библеотеку Б, только другой версии (скажем, старой). Придется собирать библиотеку С самому, добавлять ее в свой собственный Maven репозиторий. Когда придет время обновить библиотеки (например security issue где-то исправили или нужна новая функциональность или performance improvements, много может быть разных причин) то внезапно задача будет не тривиальной. Иногда даже код библиотеки С приходится править, т.к. в библиотеке Б сменился API.
      Чем больше у вас Java библиотек в проекте, тем больше вероятность таких проблем.


      1. SerCe
        20.01.2016 09:46

        Если таки столкнулись с проблемой, а вам позарез нужна эта либа:

        1. Создаем в проекте модуль D, D зависит от C
        2. Собираем D как shade-jar
        3. Делаем главный модуль зависимым на артефакте D
        4. ???
        5. PROFIT


        1. grossws
          20.01.2016 10:05

          До первой библиотеки, которая использует reflection для загрузки своих кусков или ситуации, когда один и тот же объект должен попасть и в B, и в D, но оказывается несовместим, т. к. один и тот же интерфейс представлен в runtime двумя версиями (из B и из D).


  1. bogolt
    15.01.2016 15:14

    Быть может, если вся задача сводится к тому, чтобы сохранить какое-то изображение в *.png — файл, можно обойтись системными функциями.

    Можно сделать отдельное приложение, слинкованное с этой библиотекой и реализующее нужные функции.


  1. aml
    15.01.2016 15:17
    +3

    Всеми руками и ногами поддерживаю автора! Зависимости — настоящий бич любого более-менее сложного проекта. Но с одной оговоркой. Когда предметная область, решаемая библиотекой, сложна сама по себе (например, реализация HTTP), то каждая новая библиотека обречена проходить по всем граничным случаям.

    Я как-то раз пилил процедурную генерацию 3D-моделей и мне надо было сделать объединение многогранников. Там зубодробительная математика — ошибок элементарно было наделать кучу, решил библиотеку использовать. На выбор было несколько библиотечек — пара маленьких и один огромный пакет для вычислительной геометрии. Решил маленькую использовать — вот геморрой был. Одна так и не завелась, только время потратил. Вторая заработала. А потом началось веселье: попадается вырожденная грань — глючит, многогранники касаются — падает. В каком-то из случаев вообще напоролся на TODO в коде. Пришлось использовать монстроидальную библиотеку — зато всё заработало сразу.


    1. yar3333
      15.01.2016 16:59
      +1

      Согласен с вами на 100%. В своё время не смог даже найти РАБОТАЮЩУЮ либу для поиска пересечения пары кривых Безье. Опыт как у вас: как ни странно, более монструозные библиотеки с большей вероятностью работают корректно.


  1. Gorthauer87
    15.01.2016 16:04
    +5

    Просто в плюсах нет встроенного менеджера зависимостей. С тем же crates.io особых проблем библиотеку подключить не наблюдается.
    Плюс стоит пользоваться только теми библиотеками, авторы которых имеют нормальную культуру разработки. А лишний раз лезть в api операционной системы тоже идея не слишком хорошая — это лишает кроссплатформенности.


  1. yar3333
    15.01.2016 16:55

    Во многом согласен с автором. В моём немаленьком проекте (NanoFL) используется пара чужих библиотек и десяток-другой самописных (и выложенных в open-source). Почему так? Большинство не очень распространённых открытых библиотек являются велосипедами в том или ином виде. Т.е. это обычно толком не протестированные решения, более-менее работающие в типичных ситуациях. Нередко написанные со скрытыми ошибками даже для типичных входных данных. Приходится залезать внутрь и править. А красивого кода внутри никто не гарантирует. Однако есть в использовании чужих библиотек огромный плюс — они позволяют быстрее продвигаться проекту. В конце концов — их можно переписать когда ситуация подожмёт.


  1. VolCh
    15.01.2016 20:03
    +1

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


    Часто бывает как раз, что используется и это зло. Сначала подключаем большую «год» либу, хотя можно было бы маленькую или свою реализацию, потом в каких-то ситуациях начинаем использовать другие функции этой либы, хотя можно было бы подключить другую небольшую или свою реализацию, потом ещё, ещё и ещё и получаем десятки зависимостей, от которых практически уже невозможно избавиться. Ну а чё, уже же подключена либа, нарушим немного юникс-вэй…


  1. forcewake
    15.01.2016 22:50

    А чего ж вы тогда у себя Roslyn используете?


    1. Andrey2008
      15.01.2016 22:53
      +1

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


  1. robert_ayrapetyan
    15.01.2016 23:04
    -1

    Почему-то уверен, что недавно читал эту статью на хабре!


  1. mbait
    15.01.2016 23:15
    +9

    Извините за грубость, но это типичный трёп Windows-программиста. Давайте теперь разберём ваши «советы».

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

    Shared libraries, DLLs. И что, вы скачиваете код из репозитория каждую минуту?

    Даже если вы используете 1% от возможностей библиотеки, как правило в проект она будет включена целиком. В результате, если библиотеки используется в виде готовых модулей (например, DLL), то очень быстро растёт размер дистрибутива. Если вы используете библиотеки в виде исходного кода, то существенно увеличивается время компиляции.

    Shared libraries, DLL. Статическую библиотеку достаточно один раз скомприлировать.

    Усложняется инфраструктура, связанная с компиляцией проекта. Некоторым библиотекам требуются дополнительные компоненты. Простой пример: для сборки требуется наличие Python. В результате через некоторое время для сборки проекта нужно в начале вырастить на компьютере целый сад вспомогательных программ. Возрастает вероятность, что где-то что-то перестанет работать. Объяснить это сложно, это надо прочувствовать. В больших проектах постоянно «отваливается» то одно то другое и нужно постоянно прилагать усилие чтобы всё работало и компилировалось.

    Ночные кошмары Windows-программиста. «Что-то где-то перестанет работать» звучит как «я понятия не имею, что делаю», та картинка с собакой и компьютером, вы знаете.

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

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

    У вас будут проблемы при переходе на новую версию компилятора. Обязательно будет несколько библиотек, которые не будут торопиться адаптироваться под новый компилятор. И вы будете вынуждены ждать или самим вносить какие-то проявки в библиотеки.

    Но нормальные компиляторы сохраняют обратную совместимость… Ах да, Visual C+…

    У вас будут проблемы при переходе на другой компилятор. Например, вы используете Visual C++, а хотите использовать Intel C++. Обязательно найдется пара библиотек, с которыми что-то не заладится.

    В жопу такие библиотеки, которые писали разработчики, которые не знают стандартов.

    У вас будут проблемы при переходе на другую платформу. Не обязательно даже на «сильно другую платформу». Достаточно захотеть превратить Win32 приложение в Win64. У вас будут все те-же проблемы. Несколько библиотек к этому окажутся не готовы и будет непонятно, что с ними делать. Особенно неприятна ситуация, когда библиотека заброшена и более не развивается.

    В жопу такие библиотеки ещё раз.

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

    Наверно самый адекватный совет. Тут действительно ничего не поделаешь. Можно сделать обёртку для проблемных библиотек. Но опять же — если код не из 90-х, то стоит задуматься о его качестве, если имена экспортируемых символов не содержат стабильного префикса.

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

    А как же сотни проектов, которые не разрослись, но зависят от других библиотек? Ещё существует опциональное включение.

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

    Лучше вообще код не писать, это дело наблагодарное.

    А теперь по существу. «Библиотеки» являются одной из бесконечного множества проблем разработки наравне с goto, C vs. C++, shared vs. static и т.д. Все эти проблемы объединяет то, что их нельзя решить однозначно. Прямо как в сказке про дудочку и горшочек. И когда я вижу, как кто-то в очередной раз выходит и «открывает глаза» на то, как делать правильно, то у меня два варианта: или у человека мало опыта, или человек живёт в своём маленьком мирке, где ему уютно и тепло.


    1. Hellsy22
      16.01.2016 03:18
      +9

      Давайте разберем.

      У меня на одном проекте порезвились любители добавлять библиотеки. CPAN ставит их минут 15-20.

      Нужна новая копия? CPAN. Обновился perl? Придется запускать CPAN на всех копиях — из-за конфликтов версий библиотеки ставятся в локальную, а не системную директорию.

      Ночные кошмары Windows-программиста.

      Ночные кошмары любого программиста, работающего в команде над большим и долгим проектом.

      Но нормальные компиляторы сохраняют обратную совместимость

      Недавно обновил gcc с 4.9.3 до 5.3.0, часть пакетов отказалась собираться. Посижу еще год на 4.9.
      Perl не компилятор, но на пути с 5.16 до 5.22 ухитрился потерять поддержку старого Catalyst — проект запускается, но потом падает с ошибками. А новый Catalyst несовместим со старым кодом.

      В жопу такие библиотеки, которые писали разработчики, которые не знают стандартов.

      Для этого нужно всезнание.

      когда библиотека заброшена и более не развивается.

      О, а для этого нужны еще и навыки прорицания.

      у меня два варианта: или у человека мало опыта

      Какой чудесный самострел.


      1. mbait
        16.01.2016 03:57
        +3

        И что вы хотите сказать своим примером? Мой комментарий не был оппозиционным, я не говорил «Да, давай, вперёд — добавляй библиотеки в проект!». Я просто показал несостоятельность тезисов автора. Для любого языка и платформы можно найти пример, когда получается dependency hell. Выше кто-то написал, что для Java это неактуально. Как раз таки более чем, в случае, когда A и B обе зависят от C разных версий (пожалуйста, Java-адепты, не нужно набегать, я знаю, что это проблема решается, просто привёл пример).

        Другое было бы дело, если бы автор написал
        В разработке ПО существует фундаментальная дилемма — использовать только свой код или брать чужой. На примере нашего проекта я покажу, как мы оценивали «за» и «против», принимая решение о включении той или иной библиотеки в проект.


        Ну и ещё надо быть честным — это блог PVS-Studio. Её авторы знамениты своими эпатажными постами и комментариями. Взять хотя бы их доводы по поводу Linux-версии анализатора. По ним и по этому посту складывается впечатление, что их анализатор жестко привязан к Windows, что у любого нормально программиста вызовет большое «Как?!». Поэтому сомневаться в сомнительности их «советов» не приходится.


        1. Hellsy22
          16.01.2016 04:19
          +8

          Я хочу сказать, что названные выше проблемы не ограничиваются разработкой под Windows. Я сталкивался ровно с теми же, хотя под винду за последние 15 лет не написал ни строчки кода. Сторонние библиотеки меняются и отмирают. Люди, инициировавшие их включение — покидают проект. Оставшимся приходится разбираться со всем этим наследием, которое после определенной критической массы начинает создавать проблемы с завидной регулярностью: постоянно что-то отваливается, что-то оказывается несовместимым.

          Чаще всего для исправления ситуации нужно написать буквально пару строк. Но вот только определение места, где и как их надо написать иногда занимает часы. А в случае неявных багов — дни и даже месяцы.

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


        1. Andrey2008
          16.01.2016 08:16
          -4

          Поэтому сомневаться в сомнительности их «советов» не приходится.
          С технической точки зрения Linux не проблема (Проверка Vim при помощи PVS-Studio в GNU/Linux). Другое дело, что там деньги зарабатывать не получается.


          1. 0xd34df00d
            17.01.2016 21:43
            +4

            У Coverity отлично получается. И у Intel получается. И у ряда других компаний, у которых фирма, в которой я работаю, покупает порядком лицензий, получается, видимо.

            Intel'овские продукты вроде всяких профайлеров и прочих inspector'ов, кстати, в нашу команду принёс и посоветовал купить лично я, пользуясь опытом личного использования, для которого мне не приходилось доказывать Интелу, что я стою того, чтобы на меня тратить время, в отличие от PVS.


    1. 0xd34df00d
      17.01.2016 21:39
      +1

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

      Но нормальные компиляторы сохраняют обратную совместимость… Ах да, Visual C+…


      gcc в пятой ветке сломал ABI, добавив такую вещь, как ABI tag. Поэтому на системе, собранной gcc 5, другие компиляторы чувствуют себя не очень хорошо. Например: llvm.org/bugs/show_bug.cgi?id=23529

      Лично у меня от этого возникла довольно забавная ситуация, кстати, когда кусок одной моей софтины, использующий C++14, может быть собран только на системах с gcc =4.9 и clang ?3.4, потому что даже gcc 5.3 недостаточно корректно поддерживает C++14, а вставлять костыли под него мешает эстетическое чувство.


      1. mbait
        17.01.2016 21:43

        Может я неправ, но изменение major версии предполагает возможное изменение ABI.


        1. 0xd34df00d
          17.01.2016 21:45

          С одной стороны — да, предполагает. С другой стороны — clang уж скоро год как на современных дистрибутивах по факту не работает, что несколько печалит.


        1. phprus
          19.01.2016 14:35
          +2

          В этом случае принято менять major компоненту soversion, чтобы не было проблем с ABI.


          1. AEP
            19.01.2016 16:08

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


            1. 0xd34df00d
              19.01.2016 16:17

              Веселуха начнётся, когда программа втянет две разных версии по зависимостям в одно адресное пространство.


  1. erlyvideo
    16.01.2016 21:41

    Короче, резюмирую.

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

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

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

    Статья хорошая, мысли правильные. Спасибо.


  1. Pilat
    17.01.2016 02:11
    +2

    Пример использования большой сторонней библиотеки.

    Несколько лет назад в перловом мире был бум Moose.
    Я сделал на нём большой проект. На Moose v1. Сейчас проект надо обновлять. А установить Moose v1 из CPAN не получилось — так как у него в зависимостях стоит… Moose v2 :) который с ним не очень совместим.

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


    1. erlyvideo
      17.01.2016 10:56
      -2

      ещё стоит придерживаться золотого правила о минимуме зависимостей у библиотек.


  1. Maccimo
    17.01.2016 11:34
    +1

    >> В процессе разработки анализатора PVS-Studio

    До этой строки был уверен, что читаю перевод госпела какого-нибудь североамериканского блоггера.

    Из терминальных случаев:
    Как-то раз на глаза попался java-проект с Guava в зависамостях.
    Из всего богатства Guava использовались ровно 2 (ДВА!) статических метода, Lists::newArrayList() и ImmutableList::copyOf()


  1. veitmen
    19.01.2016 11:21
    +3

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

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

    В общем почитать стоит какие проблемы есть, но давать это в виде утверждения — не профессионально, КМК.


    1. VolCh
      19.01.2016 11:37
      +2

      где риски меньше или где они могут нанести меньше вреда.

      Не «или», а «вероятность осуществления риска умножить на его стоимость». Если грубо.


      1. veitmen
        19.01.2016 14:55

        Да, приятно вас послушать. :)


  1. roman_kashitsyn
    19.01.2016 12:52
    +1

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

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

    Путём минимального препроцессинга шаблона и использования динамического программирования можно построить матчер, не использующий бэктрекинг, и работающий за O(размер строки * размер шаблона).

    А если нужно матчить сколь нибудь большие строки, лучше всё же взять RE2.

    Implementing Regular Expressions
    A Regular Expression Matcher


  1. whitepen
    19.01.2016 14:04

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