Pull to refresh

Comments 40

Очень хочется видеть в комментариях конструктивную критику поста, а не указания на опечатки автора.
А в статье критиковать то по сути и нечего, ибо она представляет на самом деле просто развёрнутую иллюстрацию в приложении к рефакторингу тезиса: «нужно всё время оценивать эффективность и последствия своих действий и стараться выбирать оптимальную стратегию»
Вещи очевидные, но зачастую упускаемые из виду разработчиками.
Сейчас все еще часто можно прочитать статью по паттернам проектирования. Баян страшный, но иногда бывают полезными и статьи и книги (Head First Design Patterns тому пример). Кроме того, в разное время (речь о проф. карьере) одна и таже информация воспринимается человеком по разному. Так что, :bear: И надеюсь, что и этот поток сознания найдет свою аудиторию.
Все очень конструктивно. Спасибо!
Основная идея очень правильная. Программист создает программы и результатом его работы является тот результат, который выходит из этих программ, а не код как таковой.
Если программист не просто кодер (это не ругательное, просто есть такой по своему полезный вид :)), то он это прекрасно понимает и старается совместить красоту кода, оптимальность потраченного на это время и результативность готовой программы.
На практике у меня возникло ощущение, что закон парето в программировании выглядит как 99:1, если за 100% брать продукт, который можно отдать заказчику. Сама программа появляется очень быстро (1% времени), и даже что то работает, и возникает ощущение, что еще чуть чуть и все готово. Потом начинаются многие часы работы (99%) времени, что бы можно было отдать заказчику.
По поводу кода:

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

В наших реалиях все выглядит так клиенту нужна программа его не волнует какой из кодов там присутствует.
Формально нужен не рефакторинг, а нужно переодически проект проверять на тему соглашений проектных, и при возможности чуток переделевать. Но отдавать 100% времени рефакторинг ради рефакторинга не разумно. С нашей колокольни хочется идеальности с жизненной стороны клиента, его мало волнуют шедевры, иногда бывает плохое допущение со стороны разработчиков не в космос летим, и качество плывет…
Посмотрите по поводу указанной в самом начале метафоры технического долга; рефакторинг — не сверический конь, он призван выплачивать технический долг (или доставлять моральное удовлетворение автору, кстати, в этом случае этот синдром хотя и вредный, если имеет патологическую природу, но есть в нем и положительная сторона). А метафора технического долга позволяет говорить с пользователем на одном языке, приводя в качестве аргументов, не технические доводы, а экономические.

З.Ы. Да, оценить точную величину технического долга сложно. Фаулер считает (Cannot Measure Productivity), что это невозможно, хотя есть и другие мнения (гугл).
У нас в проекте требования к юнит-тестам очень серьезные — должно быть покрытие не менее 80% функционала. Это требование часто выходит боком, т.к. бывает очень сложно к коду написать нормальный тест. К тому же требование написания UT часто меняют способ проектирования системы, т.е. не всегда на код можно написать UT, когда он обладает большой связностью. Но сейчас я понимаю, что уже не могу программировать без юнит тестирования. Для меня это дико, что кто-то не пишет тесты на свой код.
TDD это одна из практик, в некоторых местах без нее никак, в некоторых она не нужна… Как бы не спасают плохой код, хорошие тесты:) Всегда есть всякие НО Ну Нормализация Баз данных, ну отлично, когда надо оптимизировать скорость, происходит денормализация под конкретную версию и так далее…
Да, TDD плохой код не спасают. Однако, когда ты пишешь UT на каждый свой кусок, у тебя формируется привычка и ты уже не можешь по другому. Твое написание программы и стиль мышления при этом трансформируются. Но самое главное — что ты уверен, что вот этот кусок работает правильно, поэтому можешь спокойно писать другой кусок, основанный на нем. Это сберегает нервы и время на дебагинг.

Но, конечно, этот подход не всегда применим, да.
Вобще главное здравый смысл, а практики подбираются исходя из проектов и требований. В коммандной разработке без TDD, контроля версий и прочих инструментов/практик, будет хаос. Я согласен полностью с вашим мнением.
Я не пишу тесты на свой код, я пишу код на свои тесты :) Писать тесты после кода занятие, по-моему, и малопродуктивное, и малоинтересное.
Это как раз и называется TDD. А тесты писать после кода вполне можно. Хуже, когда они вообще не пишутся. Но TDD лучше.
Я в курсе. Вставил коммент, потому как вы с bazilxp быстро перешли с тестов вообще к TDD, а многие (вас не имею в виду) искренне считают, что раз они покрывают существующий код тестами (которые иногда непонятно что тестируют и тестируют ли вообще), то значит используют активно модную TDD, обращая внимание на test, но придавая мало значения driven. Стараюсь по мере возможностей развеивать это заблуждение :)
С автором полностью согласен. И мне кажется что подобные ошибки совершают все программисты. У них как и у автомобилистов, через 1-2 года наступает момент, когда он почувствовав свою «силу», начинает считать себя самым умным. И ленится разбираться в чём-то чужом. Однако в настоящих больших проектах, это умение я считаю основным.
От себя хочу добавить, что иногда приходится тратить на рефакторинг гораздо больше времени, чем 20%. Например, когда на систему вдруг обрушивается популярность, и она начинает экспоненциально (возможно и меньшими объёмами), но расти. Такие события лучше предугадывать конечно заранее. Но сам сталкивался с таким не раз. В итоге система эволюционирует на более современные и прогрессивные технологии. А в процессе переписывания, очень часто находятся и закоренелые баги. Ну конечно же и добавляются новые. Это жизнь.
По поводу 20% я имел ввиду несколько иное: если взять за 100% усилий, вклад человека для доведения системы до идеала путем рефаторинга, то за первые 20% усилий вы уже получите 80% результата. А все оставшиеся 80% усилий, пойдут лишь на 20 процентный остаток доведения системы до идеала.
Идеала в принципе не существует. При прохождении 50% до него, всегда остается пройти еще 50%.
Небольшое дополнение к симптому №3.

В свое время Фредерик Брукс писал об эффекте второй системы. Суть эффекта в том, что проектировщик в силу отсутствия опыта или времени накапливает идеи и решения в одном проекте, а потом выплескивает все это безобразие в другом/новом проекте.

Подобную тенденцию можно наблюдать не только у архитекторов, но и у рядовых разработчиков, который бросаются на проект с мыслью «В прошлый раз у меня не было такой свободы. А вот сейчас я все сделаю правильно!».

Лечить эту болезнь можно мягко, в бесконечных дискуссиях воспитывая в человеке внутреннюю дисциплину, или жестко, продавливая стратегические решения.
Спасибо за статью. Хочу добавить кое-что из личного опыта работы.
Симптом#1 можно предотвратить если ввести в компании правило совместного владения кодом, и, напр., устраивать code-review для программистов не самого высшего уровня.

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

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

Review быть обязан — каким бы опытным не был разработчик, к своему творению в первые дни он относится как ТВОРЕНИЮ, а потому не видит многих явных проблем. А что бы цензор, в это время принасил реальную пользу, он как раз и должен заняться рефакторингом (без лишних разговоров с рецензентом, он все равно о всем узнает). Это наложит некоторую дополнительную ответственность при написании тестов, но от этого система только выграет.
Да, все эти аспекты, в купе со здоровым прагматизмом (полностью связывать руки разработчиков — та же хрень, что и позволять переписывать все подряд, даже хз, что хуже) рулит.

З.Ы. По поводу совместного владения кодом в гугле, когда-то ваял одну заметку: Совместная работа над кодом в компании Google.
Спасибо за интересную ссылку. У нас в DevExpress в принципе подобная схема с общим доступом всех ко всему, но менее жесткая на закладки. Так что руки разработчиков не так связаны. )
Валидность закоммиченного в коде-репозиторий отслеживается через Continuous Interation, так что некорректные закладки сразу будут отражены в сломанных тестах с оповещением сломавших и должны быть сразу же пофикшены или временно может быть сделан роллбэк.
Review быть обязан — каким бы опытным не был разработчик

Это должно быть на усмотрение компании — жесткого требования может и не быть.
Да, коде-ревью, бесспорно полезно, но в любом случае отнимает время и создает излишнюю «бюрократию» в хорошем смысле слова. Для опытных разработчиков с массовым количеством закладок ревью проводить слишком накладно — это может быть сдвиги по времени и прочие факторы. А для менее опытных, вполне разумно придерживаться это правила, предварительно перед закладкой «выправив» его код, т.к. обычно скорость их разработки меньше и даже среднего-класса разработчик может выполнить ревью.
Я не имел в виду review перед выкладыванием (я выкладываю 1-3 раза в час — бедный цензор). Да и не review в чистом виде, а рефакторинг. Я говорил о том, что любой код должны увидеть минимум двое (с точки зрения review — создатель и цензор). Может через неделю, может через месяц после создания.

Вы говорите о review, как о мере обратно пропорциональной доверию. Я как о способе привлечения свежей головы. Это даст пользу даже если вы гуру, а цензор — достаточно смелый студент 4-го курса (если он обладает навыком рефакторинга и работает в основном руками, а не языком). Рефакторинг достаточно механическая деятельность (при наличии тестов конечно).

По поводу компании сказано хорошо: мы, в конце концов, все делаем по ее усмотрению. За это и получаем зарплату.
Что-то мне непонятно следующее: у вас в двух пунктах из трех проходит мысль «хороший код — красивый, отформатирванный код». Но это же мелочи — достаточно настроить правила оформления в IDE/редакторе, а потом автоматически форматировать весь файл нажатием одной кнопки.
Не понимаю, зачем на этом так заострять внимание. Мне кажется, примеры мотивации переписать код — несколько надуманные.

А в переписывании/рефакторинге есть позитивный момент: пусть лучше разработчики его воспринимают код как гибкий пластичный материал, которые можно подстроить под свои нужды; потому что очень часто встречается другой крайний случай: «это мой код, он великолепен, как ты посмел его трогать, ты сомневаешься в моей адекватности?!» и «оооо, сколько кода, давайте не будем тратить время на то, чтобы понять, как он работает, у нас же есть разработчик, которые его написал, он его знает; и вообще можно сломать»

Моё мнение, что достаточные основание для переписывания/рефакторинга кода следующие:
— код не делает то, что он обязан делать;
— код непонятен членам команды.
И в том и в другом случае надо не бояться его менять.
Cудя по количеству холиваров типа «табы или пробелы в коде» большинство вообще не знают, что такое нормальные IDE/редакторы. Создается такое ощущение, что все пишут код в блокнотах с подсветкой синтаксиса, как описано в 95% «мануалов по программированию» и компилятор вызывают исключительно из командной строки с собственноручным конфигом на n тысяч строк.
Давно не заморачиваюсь над форматированим кода, у всех коллег стоят форматтеры кода с одинаковыми настройками в diff-просмотрщике системы контроля версий стоит галочка «ignore whitespases»
А если мне не нравятся IDE/редакторы?
А как вы без редактора? Выстраиваете магнитные домены на жестком диске при помощи иголки и электромагнита?

В любом случае вы пользуетесь каким-то редактором. Для подавляющего большинства редакторов существуют какой-нибудь code beautify как плагин, скрипт либо внешнее приложение, вызов которого можно встроить в редактор.
Тогда и хабр не был бы завален одно время статьями «Tabs vs spaces блеать»
Под фразой IDE/редакторы следует понимать специализированный софт для разработки ПО.

Вторая часть вашего поста верная.
Ваша фраза примерно звучит так «мне не нравятся электродрели, поэтому я зажимаю сверлов струбцину и кручу руками» ССЗБ короче
Каждый использует те рабочие инструменты, которые ему больше всего нравятся. И осуждать меня за то, что я не следую за модой и не использую IDE, это равносильно холивару про пробелы и табы. Цель одна — добиться эффективности в работе, а это можно сделать множеством способов. И нет панацеи от всех проблем.
> насколько бы ни были понятными требования, как бы ни был выразителен язык программирования, как бы ни был хорош код и как бы он не был отлично задокументирован (хотя все эти сочетания в одном месте никогда не встречаются)

Почитайте опенсурсные библиотеки Edi Weitz для Common Lisp. ;)
weitz.de
Рост энтропии ПО не только в указанных выше причинах, но и в энтропии оборудования / программной платформы (ОС)
Скажем, было ПО для оборудования. Железо уже успело поменяться (может, даже не 1 раз), а новое железо не совсем совместимо с ПО.
То же касается и платформ — возникновения новых API, удаление или изменение существующих, изменение логики или архитектуры. Т.е., к примеру, ПО все еще актуально (относительно), но на новых системах не запустится из-за отсутствия в них нужных функций или просто из-за отсутствия в ПО поддержки 64 разрядности
Рефакторинг должен решать какую-то коммерчески обоснованную задачу. Если он этого не делает, то мне жаль компанию, которая занимается этим за свой счет. В своих проектах для себя можно делать рефакторинг хоть до посинения.

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

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

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

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

«Бытует мнение, что программные системы не поддаются старению» — у кого из программистов оно бытует-то?! Все давно поняли, кроме самых новичков. Да и те поддакивают, если хоть раз услышат =)

По статье:
сам люблю писать так развернуто. Правда, затем перечитаю, вспомню о своем стремлении к самолюбованию и самослушанию/самочитанию, и

стираю нахрен большую часть красивостей, а остальное переписываю короче раза в три.
>> «Бытует мнение, что программные системы не поддаются старению» — у кого из программистов оно бытует-то?! Все давно поняли, кроме самых новичков. Да и те поддакивают, если хоть раз услышат =)

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

>>По статье:
Я хз, у меня как попрет. Очень часто бывает, что начинаю статью, иду в одну сторону, бросаю этот кусок и переписываю заново, получается совершенно другая статья. Ну, а тут, что вышло, то вышло:) Во многом баян, но как правильно когда-то высказались ДеМарко с Листером (кажись в «наркоманах»), часто бывает полезным вынести некоторые суждения (или паттерны поведения, если хотите), на вербальный уровень. Тогда с их помощью значительно легче коммуницировать с другими людьми.

З.Ы. Вот блин, опять многовато букав:)
У вас ошибка в статье. Высокая связность (cohesion) — это наоборот хорошо. А вот жесткая сопряженность (coupling) — плохо.
не знаю как у других на проектах, но я встречаюсь в основном с проблемой отсутствия рефакторинга: говнокода в 2-3 экрана, фразами типа «это синдром рефакторинга, не нужно ни чего менять» — одним словом всем тем, с чем призывают бороться все опытные архитекторы и разработчики и чему яростно сопротивляются все те, кто себя таковыми считает, но по-сути является говнокодерами.
А как результат — код еле-еле можно протестировать и очень сложно рефакторить в дальнейшем.
Sign up to leave a comment.

Articles