Пост «Удаление кода» Неда Бэтчелдера (Ned Batchelder) недавно появился на HN, хотя изначально он был написан в 2002 году. Здесь я хочу повторить несколько мыслей Неда, и занять более решительную, чем он, позицию: удаляйте код, как только вы замечаете, что он больше не нужен, без лишних вопросов. Я также предложу некоторые советы из окопов, как определять кандидатов в мертвый код.

То что мертво умереть не может!


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

Каждый раз, когда вы хотите внести изменения, необходимо учитывать, как они взаимодействуют со всеми существующими функциями, «костылями», известными ошибками и ограничениями окружающего кода. Это легче сделать, имея меньше кода вокруг объекта, который вы хотите добавить, т.к. при этом нужно будет учитывать меньше вещей и будет меньше вариантов, что что-то пойдет не так. Мертвый код особенно вреден, потому что кажется, что нужно учитывать взаимодействие с ним, но, поскольку он мертв, это всего лишь отвлекающий маневр. Он не может принести пользу вам, так как никогда не выполняется.

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

Он должен уйти


Нед (Бэтчелдер, не Старк) был немного более деликатным и тактичным, чем я в этой статье:
Скажем, у вас есть превосходный класс, который имеет кучу методов. В один прекрасный день вы обнаруживаете, что некий отдельный метод больше не вызывается. Вы оставите его или удалите?

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

Я скажу так: выжигайте землю и не оставляйте код в живых. Лучший код, это код которого у вас нет.

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

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

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

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

Как мы сюда попали?


Пост Неда в подробностях объясняет, как и почему возникает «мертвый» код — возможно, тот, кто вносит изменения не считает, что код должен исчезнуть навсегда и комментирует его или добавляет условную компиляцию. Возможно, человек, делающий изменения не знает достаточно, чтобы понять, что код на самом деле мертв (об этом расскажу позже).

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

Лень, в конце концов, одна из трех великих добродетелей программиста. Но лень, про которую говорит Ларри Уолл другого рода: «Качество, которое заставляет вас прилагать больше усилий, чтобы снизить общие затраты энергии». С этой точки зрения, удаление мертвого кода это Лень с большой буквы Л — делать что-то, что легко сделать сейчас, чтобы уберечь себя от необходимости делать что-то сложное в будущем. Мы все должны стараться развивать такую Лень. Мне нравится думать о ней, как о «дисциплинированной лени», нашей ежедневной привычке.

Как нам выбраться отсюда?


Я провожу большую часть своего времени программируя на Python, для которого, к сожалению, IDE обычно не могут правильно анализировать полную кодовую базу и автоматически находить никогда не вызываемый код. Но, сочетая дисциплину и некоторые инструменты для анализа программы во время выполнения (run-time tooling), мы можем подойти к этой проблеме с двух сторон.

В простых случаях, хорошее чувство кода может помочь выявить и удалить мертвый код в то время как вы вносите изменения. Представьте, что вы работаете над определенной функцией и замечаете, что одна из веток if/else никогда не может быть выполнена. Я называю это «dead code in the small»* и его довольно легко заметить и удалить, но это требует немного больше усилий, чем можно было бы потратить.

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

Другой вид мертвого кода появляется при удалении последнего, использующего его класса или функции, когда ты вносишь изменения, не понимая, что это последнее место, которое его использует. Это «dead code in the large»*, и его труднее обнаружить в ходе обычного программирования, если только вам не повезло обладать эйдетической памятью, или знать кодовую базу как свои пять пальцев.

Вот когда нам могут помочь инструменты для анализа программы во время выполнения. В Magnetic мы используем пакет Неда (да, того же Неда) coverage.py, чтобы помочь нам принимать решения о мертвом коде. Обычно coverage используется во время тестирования, чтобы гарантировать, что ваши тест-кейсы правильно выполняют тестируемый код, но мы также используем его в нашем коде «работающем как обычно», чтобы понять, что используется, а что нет:
import coverage

cov = coverage.Coverage(
    data_file="/path/to/my_program.coverage",
    auto_data=True,
    cover_pylib=False,
    branch=True,
    source=["/path/to/my/program"],
)
cov.start()

# ... делаем что-нибудь ...

cov.stop()
cov.save()

Здесь создается объект Coverage с несколькими опциями, чтобы сделать отчет более удобным. Сначала мы говорим ему, где сохранять свои данные (мы будем использовать их позже, для создания удобного HTML-отчета, о том что используется, а что — нет), и просим его автоматически открывать и добавлять их в этот файл с помощью auto_data=True. Далее мы просим не беспокоится об обработке стандартной библиотеки и установленных пакетов — это не наш код, так что мы можем предположить, что многое из того что он содержит, может нами не использоваться. Это не мёртвый код, который мы должны поддерживать, так что можно смело его игнорировать. Мы просим его вычислить покрытие ветвлений (выполняются ли оба состояния true и false для каждого оператора if). И, наконец, мы указываем где находятся наши исходники, так что он может соединить свои знания о том, что используется и не используется в исходном коде, для составления отчета.

После запуска нашей программы, мы можем создать HTML-отчет:
$ COVERAGE_FILE=/path/to/my_program.coverage coverage html -d /path/to/output

Который выглядит примерно так:

(полный пример HTML-отчета можно найти в документации coverage.py)

Строки выделенные красным цветом не вызывались во время выполнения программы. Эти строки (и, возможно, методы) кандидаты для удаления в качестве мертвого кода.

Я оставлю вам три предупреждения об использовании этого подхода для нахождения и удаления мертвого кода:
  1. Будьте осторожны при рассмотрении итогов работы coverage — тот факт, что строка или функция не были выполнены в течение одного запуска программы не означает, что они обязательно мертвы или недоступны вообще. Вы всё равно должны проверять код, чтобы определить, действительно ли они совершенно мертвы в вашем приложении.
  2. Вычисление покрытия означает, что ваша программа должна выполнить больше работы, так она будет медленнее, при запуске в этом режиме. Я бы не рекомендовал запускать это в продакшене, но в промежуточной среде (staging environment) или в целевых сценариях все должно быть в порядке. Как всегда, если производительность является важной задачей, вы должны точно измерить, какое влияние оказывает вычисление покрытия, прежде чем запускать его.
  3. Наконец, не доверяйте отчетам о покрытии кода во время тестовых запусков. Какой-то код может быть мертв, но тесты все равно будут запускать его; и какой-то код может быть жив, но не запускаться тестами!


Слова на прощание


Перед тобой, дорогой читатель, я должен извиниться. Я опустил важную часть поста Неда, когда цитировал его ранее.
Он говорит:
В данном случае нет простого ответа на этот вопрос, потому что это зависит от класса и от метода. [...] Грубый ответ может быть таков: если этот класс является частью фреймворка, то оставьте его, если же он часть приложения, то удалите его.

Если вы пишете библиотеку или фреймворк, а не приложение, то вопрос мертвого кода становится с одной стороны сложнее, а с другой проще. В сущности, вы никогда не сможете удалить часть публичного API (за исключением несовместимости в мажорных версиях). Фактически весь ваш публичный API это живой код, даже если вы сами не используете его. Но за внешним интерфейсом, все ещё может возникать мертвый код, и он должен быть удален.

Удаляйте свой мертвый код!



* — отсылки к парадигмам программирования «programming in the small» и «programming in the large» (прим. перев.)
Поделиться с друзьями
-->

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


  1. Vehfl
    20.05.2016 09:28
    +10

    Хуже «мертвого» кода может быть только простыня из закомментированного кода


    1. DuDDiTs
      20.05.2016 09:30
      +6

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


      1. burjui
        20.05.2016 11:08
        -1

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


        1. igorch96
          20.05.2016 12:33

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


          1. burjui
            20.05.2016 13:40

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


            1. igorch96
              20.05.2016 15:06

              Согласен.


            1. Wilk
              21.05.2016 08:12
              -1

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


    1. Crandel
      20.05.2016 10:12
      +1

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


    1. M-A-XG
      20.05.2016 10:34

      О да.
      У меня на работе хоть и есть git, но старый код почему-то не удаляется.
      Типа, а вдруг потом потребуется. :)


    1. Mixim333
      21.05.2016 16:05
      -1

      Полностью согласен.

      >тот, кто вносит изменения не считает, что код должен исчезнуть навсегда и комментирует его или добавляет условную компиляцию

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

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

      — с этим полностью согласен, в совокупности с предыдущей цитатой можно сделать вывод: если Git\SVN хранит всю историю Вашей кодовой базы, то зачем что-то комментировать — удаляйте мертвый код под чистую, чтобы он не «вонял», даже есть термин: «smell code».


      1. grossws
        21.05.2016 16:16

        Есть термин "code smell", а smell code выглядит как указание к действию


  1. aquamakc
    20.05.2016 10:11
    +1

    В компилируемых языках вполне можно #define`ами отрезать ненужные для конкретного случая куски кода.
    Выжигать надо только то, что уже ТОЧНО не нужно.


    1. DuDDiTs
      20.05.2016 10:11
      +1

      Про #define в статье упоминалось

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

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


      1. aquamakc
        20.05.2016 10:17

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


        1. DuDDiTs
          20.05.2016 10:33
          +4

          Если вы знаете, что этот код точно для чего то нужен и этот #define может когда-то выполняться, то выходит, что код не мертвый.
          Ну и эти рассуждения о мертвом коде наверное в меньшей степени полезны для компилируемых языков. Да и автор оригинала рассуждает в контексте python'a


        1. wsf
          20.05.2016 13:29
          +2

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


  1. M-A-XG
    20.05.2016 10:11

    >Мертвый код, то есть код, который никогда не выполняется в вашей программе — это реальная помеха для поддержки вашей кодовой базы.

    Утверждение неверно.

    Некоторый код может включатся / выключатся конфигами, когда нужно.
    И это должно быть явно видно в самом коде.


    1. Crandel
      20.05.2016 10:13
      +4

      Ключевое слово — «никогда» :)


    1. DuDDiTs
      20.05.2016 10:14
      +6

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


  1. nikitasius
    20.05.2016 10:51

    Страшнее это мертвый код в проекте, который в одном единственном файле на 300кб. Вот это реальный экстрим.


    1. aquamakc
      20.05.2016 11:20

      В таком случае должны возникнуть претензии к разработчику(архитектору). Я, кстати, видел такой файл. Причём это был один класс. Было мучительно больно его приводить к виду «более-менее можно понять что оно делает».


    1. gearbox
      20.05.2016 13:27
      +1

      да там уже не мертвого кода бояться надо.


      1. burjui
        20.05.2016 14:07

        Вот уж точно. На одной прошлой работе я помогал портировать на iOS игру на C++, в ней вся логика и отрисовка были заключены в одном методе на ~3500 строк. Самой большой проблемой было понять, что, чёрт возьми, в нём вообще происходит. О рефакторинге и удалении мёртвого кода я даже не заикался, т.к. там всё было построено на анти-функциональной парадигме: туча глобальных переменных, всё усыпано состояниями, как булка — маком, классы как имена для пачек процедур. В таком проекте нет понятия "мётрвый код", т.к. всё сыпется от малейшего чиха.


        1. aquamakc
          20.05.2016 14:13
          +2

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


        1. MooNDeaR
          21.05.2016 16:00

          Я вот сейчас на новой работе столкнулся с функцией на 4300+ строк. В ней прописана какая-то аццки непонятная вещь по инициализации системы. Интересно, что в том же файле определяются еще 20+ вспомогательных функций. И самое крутое — ни одного комментария. Вообще. Оно просто работает и я понятия не имею как :)


  1. ivanbolhovitinov
    20.05.2016 11:25
    +2

    Явно мертвый код надо хоронить, иногда с почестями, иногда не прощаясь.

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


    1. samizdam
      20.05.2016 23:13

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

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


  1. kamilgarey
    20.05.2016 11:33

    Боле точно это рассмотрено у Фаулера http://martinfowler.com/bliki/SacrificialArchitecture.html
    Не рассмотрен случай когда, «мёртвый код» написан тобой. (Здесь я имею ввиду код зависящий от настроек которые никогда не будут выставлены) Сам наступал на эти грабли (тащил старый код).


  1. Shamov
    20.05.2016 12:36

    А я сознательно не удаляю мёртвый код, если он реализует какую-нибудь необычную вещь, которую нельзя будет в будущем воспроизвести прямо из головы с первой попытки. Вот, например, я сначала сделал что-то одним способом. Затем придумал способ получше. Старую реализацию я оставляю прямо там, где она была, если она представляет какой-то интерес. Может в будущем пригодится в другом проекте. Вместо того, чтобы поддерживать библиотеку сниппетов с детальными описаниями, я храню интересный код прямо там, где он изначально появился. Так мне гораздо проще его находить. Когда нужно повторно реализовать что-то такое, что ты уже раньше делал, намного проще вспомнить то, в каком проекте и с какой целью ты это раньше делал, чем искать какой-то абстрактный сниппет среди сотен других. Память устроена ассоциативно.


    1. DuDDiTs
      20.05.2016 12:37

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


      1. Shamov
        20.05.2016 12:58

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


    1. aquamakc
      20.05.2016 12:45

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


      1. Shamov
        20.05.2016 13:00
        -1

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


        1. DuDDiTs
          20.05.2016 13:10

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


          1. Shamov
            20.05.2016 13:33
            -1

            Зато в контроле версий нет удобного поиска. Нужно более-менее точно помнить время, когда ещё была старая реализация. В принципе, мой способ сочетает в себе всё необходимое и лишён недостатков. Во-первых, старая реализация сохраняется вместе с контекстом её использования. Во-вторых, её всегда можно быстро найти, поскольку она есть в самой последней версии кода проекта. В любых других способах нет либо того, либо другого. Хотя, я признаю, что другие способы более правильные с методологической точки зрения. И если отсутствие методологической чистоты считать недостатком, то недостатки у моего способа всё-таки есть. Просто я быдло… и методологическая чистота не находится в числе моих приоритетов :)


            1. aquamakc
              20.05.2016 13:37

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


              1. Shamov
                20.05.2016 13:44
                -1

                Нет, другие разработчики этого мёртвого кода, естественно, не видят. В основную ветку я сливаю только то, что реально используется. Такой мёртвый код живёт только в моих собственных репозиториях. (Похоже я забыл сказать самое главное :)


            1. 0xd34df00d
              21.05.2016 01:44

              git log <filename>
              git grep
              git blame


              1. Shamov
                21.05.2016 08:12
                -1

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


                1. 0xd34df00d
                  21.05.2016 18:16

                  А как вы тогда в вашей системе ищете конкретный код? Ну, конкретный файл и конкретные строчки в нём?


                  1. Shamov
                    21.05.2016 18:36
                    -1

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


                    1. 0xd34df00d
                      22.05.2016 21:36
                      +1

                      Так если вы знаете, в каком проекте/файле вы это уже делали, то вы точно так же можете натравить эти замечательные команды на эти файлы.


                      1. Shamov
                        22.05.2016 22:25

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

                        Давайте предположим… просто ради смеха, что grep — не самый лучший инструмент для поиска кода. Вам когда-нибудь удавалось найти с его помощью хоть что-то в коде, если это был не print() с сообщением об ошибке? Не предложить кому-нибудь сделать это, а реально найти что-нибудь самому…


                        1. 0xd34df00d
                          23.05.2016 05:48

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


                          1. Shamov
                            23.05.2016 06:55

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


                        1. gearbox
                          23.05.2016 14:50

                          Вам когда-нибудь удавалось найти с его помощью хоть что-то в коде, если это был не print() с сообщением об ошибке?

                          Пользуюсь grep, знакомство с чужим проектом практически всегда начинается с него. Да, сижу в vim, а не в IDE. Нет, потребности не ощущаю. Да, работал в IDE, вкус устриц знаю.


                          1. Shamov
                            23.05.2016 14:55

                            Отлаживаетесь, наверное, в чистом gdb…


                            1. 0xd34df00d
                              23.05.2016 15:23

                              Более того, gdb использую лишь для получения трейсов.


                              1. Shamov
                                23.05.2016 15:37
                                -2

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


  1. wsf
    20.05.2016 13:28

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


  1. BalinTomsk
    20.05.2016 17:05
    -1

    Чем хороши Delphi и C# тем что в режиме отладчика там видны методы, которые никем не вызываются и их можно удалить


    1. grossws
      20.05.2016 17:30
      -1

      И что, методы вызываемые через reflection по имени на базе пользовательского ввода тоже подсветит как используемые?


      1. burjui
        20.05.2016 17:49

        Не в курсе, как в Delphi и C#, а в Java такие методы разработчики обычно аннотируют:


        @SuppressWarnings("unused")
        public void doSomething()
        ...

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


        1. grossws
          20.05.2016 18:15
          -2

          Вы, наверное, также аннотирует весь public API, если пишите библиотеку, да?


          1. grossws
            21.05.2016 23:01
            -2

            Не стоит так обижаться на сарказм.


            1. burjui
              22.05.2016 13:04
              +1

              Вы преувеличиваете мои возможности (см. профиль), к тому же, я не испытываю боли ниже поясницы из-за комментариев в интернете, на которые я даже не отвечал. Каждый имеет право высказаться.


  1. 1vanK
    20.05.2016 17:57
    +1

    Мне тоже доставляет удовольствие удалять код на питоне)


  1. Stas911
    20.05.2016 19:45

    Почему нужно удалять старый код: тыц


  1. samizdam
    20.05.2016 23:19
    +1

    За последний код, осознал, что мне больше нравиться коммитить удаления строк и файлов, чем добавлять их.
    Просто физическое удовольствие, когда git status выводит жирный список deleted, от предвкушения предстоящего коммита =)


  1. netpilgrim
    28.05.2016 16:20
    +1

    Идея. В continuous integration прикрутить систему ачивок для стимуляции хороших практик:
    «уборщик кода» — больше всех удалил кода
    «нинзя» — не сломал ни одного теста
    и т. д )


    1. DuDDiTs
      28.05.2016 16:23
      +1

      Главное заранее хорошо все продумать.
      «уборщик кода» может до добра не довести :)