Как стать автором
Обновить

Чему я научился на своём горьком опыте (за 30 лет в разработке ПО)

Время на прочтение22 мин
Количество просмотров117K
Всего голосов 187: ↑178 и ↓9+169
Комментарии128

Комментарии 128

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

А представляете, на заре программирования в 60-е, да и в начале 70-х было четкое разделение на алгоритмистов и кодировщиков. Первые четко описавали алгориртм, который требовалось запрограммировать. И не просто описывал, а представлял в виде блок-схемы со всеми переменными и разветвлениями. И кодировщику оставалось четко следовать этой блок-схеме и переводить ее на соответствующий язык (ассемблер, автокод, Алгол, Фортран, Алмо и т.д.). Порой кодировщик и понятия не имел для чего нужна программа.
Но времена изменились. В первую очередь изменились языки. И Сегодня программист и алгоритмист, и кодировщик, и предметник и т.д. и т.п. И у него часто возникает вопрос


что делать дальше?

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

У нас КБ на ~200 человек, из них треть это технологи(алгоритмисты) и треть программисты. Так что это все действительно завязано на объеме работ.
Так вот зачем мы учили и рисовали блок-схемы 20 лет назад.

Приятно наконец узнать, что это потому, что 50 лет назад было такое разделение.

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

Интересно, а современные студенты сейчас изучают воплощение алгоритмов в блок-схемах?

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

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

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

Тогда машины стояли только в крутых конторах, которые умерли вместе с наукой и производством. И тогдашний программист мог просто не понимать, как решать поставленную задачу, если она была, скажем, сложной математической или физической проблемой. Тогда и придумали разделение на алгоритмистов и кодировщиков.
Теперь подавляющее число задач связаны с UI в браузерах и показу в нём данных из БД. Часто это понятно и человеку без образования.
Но до сих пор есть разделение, скажем, на базиста и программиста, особенно если БД типа Оракла, с кучей разнообразных фич и тонкостей. Это ведь тоже связано с определённой специализацией в сложных системах, где работают множество людей. И уже никого не удивляет.
Перевод материала Капитана Очевидность, имхо.
Кое-что очевидно тем кто хоть и немного, но уже поработал в этой сфере в соответствующей должности, кое-что очевидно тем, кто уже довольно долго работает, по-моему не очевидно все лишь тем, кто вообще никогда не программировал.
НЛО прилетело и опубликовало эту надпись здесь
Потому, что и так сойдет, чаще всего. Некогда мусолить, надо дальше бежать, и т.п.
Думать на будущее означает тратить силы впустую
Обоюдоострый совет. Нужно чутьё и опыт, чтобы понимать, когда нужно прототипировать налево-направо, а когда — сидеть с ручкой и бумажкой и рисовать замки в облаках.

Не используйте булевы значения в качестве параметров.… можете переименовать функцию getUserMessageSummaries и ввести getUserMessagesFull, или что-то подобное, но каждая функция будет просто вызывать исходную getUserMessage с true или false — зато интерфейс вовне вашего класса/модуля будет понятным.
Для этого существуют enum-ы.

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

ВСЕГДА используйте в датах часовые пояса
ВСЕГДА используйте UTC, кроме пользовательского ввода-вывода. Если с часовыми поясами работать всё-таки придётся, убедитесь, что в используемой библиотеке достаточно мало багов (от стандартных библиотек часто приходится отказываться).

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

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

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

Кто-то скажет: «Может, если ты поговоришь с этими людьми, они перестанут так делать?» Я считаю, что не перестанут.
Всегда лучше выговориться (без наездов), чем держать в себе недомолвки. Если человек не исправляется, можно ненавязчиво привлечь других людей. Хуже точно не будет.

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

А иногда наоборот лучше заменить хеш-таблицу на массив ;)
Для большинства реальных (не вырожденных искусственно) случаев в сортированном массиве поиск осуществляется с той-же скорость, а памяти кушается в 5-10 раз меньше, чем при использовании хэш-таблицы. Для больших данных и обычных компьютеров это может быть качественно лучше.А уж проще…!!!
Думать на будущее означает тратить силы впустую

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


Из названия статьи следует, что автор имеет как минимум опыт. Для тех, кто не имеет, хорошо бы знать пару-другую «гур», которые могут подсказать. Считаю пункт весьма актуальным. У кого нет чутья и опыта, об этом пункте стоило хотя бы задуматься.

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

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

Для этого существуют enum-ы.


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

Я встречал данный антипаттерн в ситуациях, когда поведение процедуры следовало изменить при определённых внешних условиях. Тогда список параметров расширялся, добавлялся N+1-ый параметр типа boolean со значением по умолчанию false. Этот параметр «включал» новое поведение. Таким образом, считалось, что весь старый код продолжал работать как раньше, а там, где требовалась изменённое поведение, вызывалась процедура с этим параметром true. Мне, например, весьма часто не было понятно, что-же этот последний true обозначает…

А так — да, enum-ы — хорошая штука.

«Правильный инструмент для задачи» — это способ навязать своё мнение

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


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

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

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

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

ВСЕГДА используйте в датах часовые пояса

ВСЕГДА используйте UTC, кроме пользовательского ввода-вывода. Если с часовыми поясами работать всё-таки придётся, убедитесь, что в используемой библиотеке достаточно мало багов (от стандартных библиотек часто приходится отказываться).


«Дата с часовым поясом» — это больше, чем UTC. По ней можно сказать, например, когда у человека день, а когда ночь. Стоит ли ждать от него скорого ответа. Стоит ли ему сейчас звонить…

Я наблюдал и участвовал в задачах перевода систем с локального времени без часового пояса на UTC и иногда потом на время с часовым поясом. В другую сторону перехода делать, по крайней мере в моём мире, никогда не требовалось. А как бы было хорошо, если бы c самого начала время просто было с часовым поясом!

Поэтому Ваш совет «ВСЕГДА используйте UTC» я рассматриваю как шаг назад по сравнению с тем, что предлагает автор. Да, если используемые библиотеки с часовыми поясами работать не умеют, ничего не остаётся, как взять только UTC. Но это для меня безысходность, а не практика, которую я бы всем предлагал.

Отладчики переоценены

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


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

Речь-то идёт о том, что будет делать разработчик, когда воспользоваться отладчиком нет возможности. Тогда-то и будет польза в умении работать без отладчика, в грамотном логировании,… etc.

Оптимизации оставьте компиляторам

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


Тут тоже для меня не всё так просто. «Если вместо дерева или хеш-таблицы вы возьмёте простой массив...» — Ваш пример я отношу к ошибкам проектирования или ошибкам при выборе структур данных. И, соответственно, то, что вы назвали «оптимизацией» для меня является процессом исправления ошибки.

Я бы сказал, что улучшениями алгоритмов стоит заниматься, как тó: замена используемых структур данных на более подходящие для Ваших условий, добавление кэширования,… etc. Впрочем, именно так я и понимаю слова автора: «О чём вам нужно думать, так это… о том, как улучшить текущий код.».

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

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

Кодекс поведения защищает вас, а не их

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


Для меня привычнее «в чужой монастырь со своим уставом не лезут».

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

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

Кто-то скажет: «Может, если ты поговоришь с этими людьми, они перестанут так делать?» Я считаю, что не перестанут.

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


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

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

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

Уф, как-то длинно получилось. Просто за душу взяло… :)
Из названия статьи следует, что автор имеет как минимум опыт. Для тех, кто не имеет, хорошо бы знать пару-другую «гур», которые могут подсказать.
Мне и самому встречались люди, которые, прочитав книжку по проектированию (или ещё хуже, по UML), лепили неведомую хрень со словами «я архитектор, я так вижу». Правда, мне пока не встречались обратные примеры, чтобы новичок узнавал о вреде оверинженеринга до получения понятия об архитектуре. Так что в контексте статьи совет действительно имеет право на жизнь.

Мне, например, весьма часто не было понятно, что-же этот последний true обозначает…
Именно поэтому нужен enum, который в нашем случае будет играть роль именованного типизованного bool-а.

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

«Дата с часовым поясом» — это больше, чем UTC. По ней можно сказать, например, когда у человека день, а когда ночь. Стоит ли ждать от него скорого ответа.
А если он — топ-менеджер, который полжизни проводит в аэропортах? Всегда найдётся частный случай, в котором фундаментальные проблемы часовых поясов будут порождать баги на уровне требований; и чем реже вы мешаете время с часовыми поясами, тем меньше будет багов.

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

то, что вы назвали «оптимизацией» для меня является процессом исправления ошибки.
Если медленная работа не противоречит требованиям, то мы тут начнём спорить о субъективных (архитектурных, стилистических) ошибках. Всё-таки оптимизация — вполне чёткое и вполне подходящее здесь понятие.

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

Да, по этому поводу автор сказал немного. Я экстраполирую его предыдущий абзац, добавляю свои ожидания помощи от отладчиков N лет назад, сегодняшние ожидания многих коллег, и соглашаюсь с утверждением. Но не берусь утверждать, что Вы неправы ;)
Весьма неплохо в целом. По последним пунктам сразу вспомнилась книга Саттона «Не работайте с мудаками»
Это тождественно выражению «не работайте». В любом коллективе есть хотя-бы один мудак (если в вашем нет — то у меня для вас неприятная новость). Это я гиперболизирую, конечно, но все-таки…
Честно говоря, прямо такого мудака как описано у Саттона я встречал только на одной своей работе и то, он был далёк от ИТ и мы с ним перескались исключительно редко, буквально пару раз. Это не значит, что с все остальные были отличными коллегами, но такой степени мудачности я больше ни у кого не припомнил.
У меня просто бывало нередко что люди в целом производившие неплохое впечатление о себе, в экстремальной ситуации так раскрывались, что просто удивляет, и таких людей, к сожалению немало. Все хорошо «до первого шухера», и тут вроде бы твой даже приятель, с которым вы вместе весело общались и грызли печеньки на обеде, вдруг тебя жестко и весьма осмысленно подставляет, что-бы прикрыть свою задницу. К сожалению это совсем не редкость.
Явно указывайте, что вам нужно. Варианты sleepForSecs и sleepForMs не идеальны, но это лучше, чем sleep.

Классная идея — включать тип аргументов в название функций. Сразу видна забота о тех, кто программирует в nano, ed'е и на бумажке. К сожалению, не раскрыта тема функций strcpyStrConstStr и timeTimeT.
Там не тип включается, а описание того, что делает функция. А сами единицы времени могут быть хоть интом, хоть классом.
Там не тип включается, а описание того, что делает функция.

Хотите сказать, что функции sleepForSecs и sleepForMs делают что-то разное, а не отличаются только типом аргумента?
(и это даже не говоря о том, что название слипФорСекс неудачное как ни посмотри)
Да. Очевидно, что спатьСекунды и спатьМиллисекунды. Пример немного надуманный, но посыл вроде понятен.
Сколько усилий вам понадобится, чтобы понять какое количество времени код будет «спать» в случае чтения:
sleep(7);
А сколько в случае?
sleepForSeconds(7);
Неплохой альтернативой в подобных случаях может быть:
sleep(7, units::seconds);
(и это даже не говоря о том, что название слипФорСекс неудачное как ни посмотри)

Почему неудачное?
Очевидно, что спатьСекунды и спатьМиллисекунды.

То есть вы не считаете, что эти две функции делают одно и то же? Интересное мнение. Не особо распространенное.

Сколько усилий вам понадобится, чтобы понять какое количество времени код будет «спать» в случае чтения:
sleep(7);

Нужно будет посмотреть сигнатуру этой функции, если я ее не знаю. Но дело в том, что эта проблема решается не дописыванием типа аргументов в название функции (и созданием кучи функций sleepForSecs, sleepForMs, sleepForYears ), а передачей в функцию sleep объекта типа Time/Duration/Chrono и т.д. Собственно, во всех разумных современных языках и библиотеках (… которые я видел ), так и сделано.

Почему неудачное?

Скрытый текст
Вот буквально недавно столкнулся с Enterprise Quality фреймворком, который ходит по коду, ищет в идентификаторах вхождения буквосочетаний «sex/fuck/vagina/cunt» во всех вариантах написания и сигнализирует об этом. Говорят, его написали после того как одна крупнейшая корпорация выпустила публичную апишку с классом с именем типа BitChangerEngine, а потом была вынуждена резко его депрекейтить. Как говорят у нас в деревне: The struggle is real!
То есть вы не считаете, что эти две функции делают одно и то же? Интересное мнение. Не особо распространенное.

В учебно-показательном примере — да, они разные, примерно как quickSort и mergeSort(ну вот мне тоже более реальные примеры в голову не идут). Еще раз, этот пункт про полноту наименования функций/методов/классов/переменных.
Нужно будет посмотреть сигнатуру этой функции, если я ее не знаю. Но дело в том, что эта проблема решается не дописыванием типа аргументов в название функции (и созданием кучи функций sleepForSecs, sleepForMs, sleepForYears ), а передачей в функцию sleep объекта типа Time/Duration/Chrono и т.д. Собственно, во всех разумных современных языках и библиотеках (… которые я видел ), так и сделано.

Да не тип туда дописывается и дополнительная(и часто необходимая) информация о действии, которая функция совершает.
Был бы тип, было бы название функции sleepTime — действительно странное название.
Есть вот эта злосчастная sleep в UNIX(принимает секунды) и в Windows(принимает миллисекунды), лучше бы они назывались соответствующе, раз в С нет возможности создавать собственные типы Time/Duration/Chrono.
По мне так вразы проще выбрать нужную функцию по имени чем передавать туда какую-нибудь шаблонную хрень типа std::chrono::duration с каким нибудь вызовом std::chrono::duration_cast<бла-бла>

А что не так с BitChangerEngine?
Тоже на некоторое время завис, но вроде понял: видимо, дело в том, что там можно прочесть «bitch».
Тогда надо запретить слова assemble, assert, assist и assess.
А Bit banging ещё не запретили?
А что не так с BitChangerEngine?

BitchAngerEngine

В этом плане по синтаксису имхо рулит обжектив-си, где можно написать, к примеру, [MYSleeper sleepForSeconds: 10.0f]; [MYSleeper sleepForMilliseconds: 1000.0f];, хотя там, опять же, есть общепринятый тип данных NSTimeInterval, равный секунде и являющийся при этом float :-)

Он же там чуть выше ратует за то, чтобы функции были документированы. Часто это гораздо лучший выход, чем копипастить почти одинаковый код в чуть разные по названию и аргументу функции
НЛО прилетело и опубликовало эту надпись здесь
Тоже вспомнил такие названия из avr-gcc
НЛО прилетело и опубликовало эту надпись здесь
Что ж тут зубодробительного? Разве что подчеркивание в начале лишнее, отдает приватной библиотечной функцией.
НЛО прилетело и опубликовало эту надпись здесь
смотря где. Бывают ситуации, требующие высокой скорости и прерывать их другими задачами нет смысла. Хотя бы SPI: что программный, что аппаратный на максимальной скорости занимают десяток тактов. Программа просто не успеет переключиться чтобы сделать еще что-то в этом огрызке времени.
Или наоборот, есть длинная и развесистая задача в основном цикле, а все остальное распихано по прерываниям. Ну и смысл городить недо-ОС, когда задача всего одна.
В общем, как везде: есть инструмент. Есть люди, применяющие его к месту. А есть обезьяны, применяющие везде. Но инструмент-то в этом не виноват.
НЛО прилетело и опубликовало эту надпись здесь
делеи не для точных таймингов в любом случае. Это скорее из серии «выждать 10 мс пока питание стабилизируется», «выждать 100 мкс когда дисплей прожует предыдущий байт»
Где нужны точные задержки, там надо как минимум прерывания запрещать. А лучше, конечно, использовать человеческие методы.
а не отличаются только типом аргумента?
Без дополнительной информации (из документации, если она не устарела) не очевидно, что они отличаются и типом аргумента.
Обе могут внезапно принимать целые (или вещественные).
Или и те, и другие. Или принимать вещественные и округлять. И считать, что 0, полученный из 0.1 означает не нулевую задержку, а наоборот: «пропустить всех остальных вперёд».
название слипФорСекс неудачное как ни посмотри)
слипФорМиз тоже могут посчитать сексистским. ¯\_(ツ)_/¯ (Кроме того, что формально «Ms» — мегасекунда.)
Если бы аргумент был объектом класса «единицы времени», то всё и так было бы понятно — секунды это или милисекунды :).
Согласен, но от языка много зависит, если память не изменяет(очень давно не писал), то в C++ вполне допустимо написать такое:
class Seconds {
Seconds(int seconds){}
};
void sleep(Seconds sec){}
sleep(7);

А еще всякие динамически типизированные языки есть или чистый C без всяких классов.
Да и еще раз — пример надуманный, но неужели у вас ни разу не возникало чувство недостаточности в имени класса/функции/переменной?
Не, недопустимо. Могут появиться травмы лица за конструктор с одним параметром и без explicit ( что как раз и предотвращает эту проблему ).
Согласен. Еще и за sleep(7) тоже можно по лицу получить, ибо магическое число. Если что-то можно выразить через типы — лучше выражать через них. Но не всегда такая возможность есть.
В C++ давно уже единственным нормальным вариантом будет
std::this_thread::sleep_for(7s);
Это начиная с 14-го.
У нас, например, пока разрешён только 11-й, поэтому

std::this_thread::sleep_for(std::chrono::seconds(7));

Включать надо не тип аргументов, а единицы измерения, причем не только в функции, но и в переменные, константы и т.п. Особенно если это настройки.
Скажем, в прошивке устройства используется таймаут, задаваемый через константу (
#define TIMEOUT 2
). В каких он единицах? Секунды, микросекунды, тики таймера? А вот если явно указать человеко-читемую единицу
#define TIMEOUT_S 2
, сразу ясно, что в секундах. Потом, для машинного представления, можно добавить формулу, по которой препроцессор переведет в тики или в чем там удобно. Но настройки должны быть человеко-читаемы.
Еще хуже с физическими величинами. Переменная
double channel_len;
в каких единицах? Но стоит добавить суффикс, и неоднозначность исчезает:
double channel_len_mm;
. А совсем хорошо непосредственно перед наложением переменных на формулу привести их к единой системе единиц (для научных формул — СИ). Разумеется, поименовав в соответствии с размерностью. Добавляется перекладывание переменных, зато меньше риск ошибки.
И в этом смысле удачно сделали разработчики Atmel со своими _delay_ms, _delay_us или, если кому ближе usleep. Гораздо нагляднее всяких Sleep, delay и т.п.
Спасибо за полезные советы. Опытным программистам они должны быть в большинстве своём очевидными.
По поводу совета «Не используйте булевы значения в качестве параметров» мне вспомнилось правило «Язык определяет сознание». В Java код
getUserMessage(userId, true)

действительно выглядит неинформативно, но в Python можно писать:
getUserMessage(userId, includeBody=True)

A в Smalltalk синтаксис предполагает многословное имя метода:
getUserMessage: userId.    //Метод с один аргументом
getUserMessage: userId includeBody: True.    //Метод с двумя аргументами
Ещё это в Swift повторили, внешние имена аргументов много где обязательны.
НЛО прилетело и опубликовало эту надпись здесь
Аттачить-то можно, только если код многопоточный, то не факт, что это поможет.
А иногда и аттачить нельзя из-за политик безопасности.
НЛО прилетело и опубликовало эту надпись здесь

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

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

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

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

Лучше всего дорабатывать процессы тестирования, чтобы ошибки до прода не доходили.


А логи и метрики обо всем рассказать не могут.

Если баг сложновоспроизводимый и пока занимаетесь только его локализацией, то вполне может быть, что конкретный клиент на баг и не попал бы, а вот на брикпоинт — попал :(

> Я узнал, как в Java работают дженерики, когда писал код на Rust. Я понял, как в Spring выполняется внедрение зависимостей, когда прочитал об этом в С++.

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

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

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

waaaaaaaaaat????
Тем более что очень часто по названию переданных аргументов всё равно нельзя сказать что там должно быть по сути.
Может 30 лет назад это было актуально, но сейчас IDE легко и просто рассказывает что там за переменная и для чего она. В целом догадываться о том, что значат аргументы по названиям переданных туда переменных — спорное удовольствие.

Дальше тоже спорные высказывания, но комментировать всё — еще одна статья получится. Тоже спорная.
Спасибо за ваш опыт! Многое из написанного — очень полезно!
сейчас IDE легко и просто рассказывает что там за переменная и для чего она

До сих пор, к сожалению, не все IDE рассказывают легко и просто. Кроме того, где-то выше был комментарий про работу в вим, блокноте и на листочке. В общем, в чем только люди не пишут и, особенно, в чем только не читают код.
В VIM нет проблем с просмотров аргументов у функции.
А в блокноте и на листочке именованные аргументы всё равно не помогут.

IDE-то рассказывают, но иногда код смотрят вообще в браузере, без всяких IDE...

Скорее даже не иногда, а очень часто — во время код-ревью

Вспоминается Qt
setVisible(bool)
и show(), hide()
очевидно что последниее более читаемые, но если у нас состояние динамическое setVisible(новоеСостояние) намного удобнее чем городить ифы.
Преимущественно люто соглашаюсь, есть о чём похоливарить («оптимизации — компиляторам», «о будущем — впустую»), но хочу у народа повыспросить другое.

Иногда вот пишешь, пишешь, и тут звоночек:
Если в описании функции есть «и», то это плохо

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

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

Да, для меня это тоже ад, но блин, где остановиться-то? Кто как такое сам для себя решает?.. Понятно, что у каждого будет как-то «по ситуации», но, быть может, существуют какие-нибудь наработанные/эмпирические правила/рекомендации?..

Я «для себя» (о питоне речь) решил, что один-два именованных (обязательно, но не всегда ))) булева параметра — допустимое зло, а стекировать функции старался уровня на три-четыре, но это я библиотек не писал… Потому что в коде библиотек встречал размазывание функций слоёв на десять и больше, и это действительно читать тяжковато…
У функций должны отсутствовать побочные эффекты, она должна делать только что-то одно, но делать это максимально хорошо. Если она написана именно так, то при ее описании не возникает желания использовать «и», и тем более перечисление побочных эффектов.
Вкрячивание булевых параметров, которые кардинально меняют поведение функции — это такой кривой костыль, автор об этом. Само собой у любого эмпирического правила подразумевается разумный подход его исполнителя (в этом основные плюсы и минусы таких правил) Любое разумное правило можно довести до абсурда если его выполнять тупо и формально, не задумываясь о последствиях.
хммм tryLock делает вот две вещи — проверят можно ли залочить мутекс и если можно лочит его.
А если функция кроме своих действий пишет статистику это побочный эффект?

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

Плохое название стоит исправить на хорошее, а вызовы подряд зачастую лучше чем вызов одной универсальной функции, на которую навешаны десяток разных обязанностей
Я воспринимаю сказанное автором следующим образом. Если именно в названии функции присутствует И, то тут, скорей всего, что-то не так. Функция с «хорошим» именем (без «и») функция при этом может делать несколько взаимосвязанных вещей, если это действие можно воспринимать… атомарно, что-ли. Понятно, что функция readFile должна и открыть файл, и прочитать его, и закрыть его. При этом у нас не возникает желания назвать такую функцию openFileAndReadItAndCloseIt.

Точно так же с tryLock. К стати, я бы описал то, что она делает, несколько отлично от Вашего варианта. А именно: пробует захватить (залочить) мутекс. В случае успеха возвращает true, при неудаче возвращает false. Но это всё ерунда, в названии-то «and» не стоит ;)

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

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


О том-то и речь! Если не получается избежать «и» или синонимичного в данном контексте «потом», «затем»,…, значит, скорей всего тут дело нечисто, и лучше писать две функции.

В целом, я вижу в этом не догму, а хороший способ проверки на вшивость своего кода. Опять же, разумные исключения/расширения в моём мире имеют право на жизнь. Скажем, в некоторых ситуациях может быть оправдано существование f1, f2 и f1ThenF2. Естественно, f1ThenF2 должна быть реализована посредством вызовов f1 и f2, а не, скажем, копированием и вставкой их тел, или, что ещё хуже, написанием кода «с нуля». Хотя и тут тоже могут быть исключения ;)

В общем, по-моему, нужно понимать, с какими именно проблемами боролся автор, и делал соответствующие «записки на манжетах». Так же нужно понимать, что записка эта справедлива для определённого контекста. Да, в 80% или в 90% случаев контекст именно этот. Но вот оставшиеся 10%… Короче, проповедую подход без фанатизма :)
Вдогонку. Неправильно понял про статистику. Общая статистика работы программы, это штука ортогональная по отношению к основной функциональности. Если средства языка позволяют её подключить ортогонально, например через аспекты, то всё здорово. А если нет, приходится исхитряться. Как-то писали генерирование прозрачных врапперов (proxy), сложенных в отдельные загружаемые библиотеки. При загрузке, либо использовались оригинальные библиотеки, и статистики не было, либо библиотеки со сгенерированными врапперами, которые догружали оригинальные библиотеки, тогда статистика была.

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

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

Вдогонку — стоит различать действия и цели. Нет смысла выносить в название функции действия, там должна быть цель. Потому название tryLock правильно, оно говорит о цели. Для достижения этой цели может быть произведено очень много разных действий, и это нормально и понятно, в этом легко разобраться и это легко поддерживать.
А вот если функция кроме того еще и пишет статистику, то у нее оказывается больше чем одна цель, и ее тоже нужно как-то вывести в название, а еще правильнее вынести достижение этой цели в отдельный код.
Флаги допустимы, були допустимы. JavaScript. Главное — написать документацию на функцию и перечислить входящие параметры. Нет ничего проще.
То же касается и пресловутого «и». Я пользуюсь правилом, что в-основном надо избегать копипаста самой функциональности. Если 95% содержимого двух функций идентичны, и это не три строки, то можно использовать «и», почему нет?
есть два варианта — или разбить на две или назвать без «и»:
например функцию «поесть и попить» называем «пообедать».
Я так понял, это его правило относится не к названию, а к функционалу: что делает функция.
if (arguments.water) return попить
if (arguments.meat) return поесть
А почему-бы просто не сделать две функции: попить() и поесть() вместо этих костылей в аргументах?
Если в таких функциях оказывается много копипасты, то это повод задуматься о том, что их так-же стоит декомпозировать и копипасту вынести в отдельные функции, которые и использовать. Да, получится что вместо одной функции у вас уже стало несколько, но такой код и понимать и поддерживать как правило намного проще, и ошибки в нем легче заметить и исправить.
Часто наблюдал в коде функции (точнее методы), размером так в пару-тройку тысяч строк, и у них тоже, как правило огромный список аргументов на входе, в котором разобраться непросто даже когда на этого монстра есть какая-то документация (а ее чаще всего нет, либо она уже сильно устарела)
Отладчики переоценены

Я бы даже сказал, что порою недооценены. Вместо брейкпоинтов и дебага испльзуют print. Как же это «весело».
Заведите список «того, что я не знаю»

Уже сделал :) Хороший совет.
Всю жизнь в php пишу echo $x;exit; Давно уже знаю и пользуюсь xdebug, но для его запуска нужно выставить флаг, включить в браузере отправку (xdebug helper), в ide включить прослушку. Короче, легче написать то что выше написал.
Бывают случаи когда приходится дебажить. Но это касается огромных структур данных, которые могут быть еще и закольцованы.

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

> Я бы даже сказал, что порою недооценены. Вместо брейкпоинтов и дебага испльзуют print. Как же это «весело».

В этом есть свой существенный смысл.
Интерактивная отладка помогает получить текущее состояние — да, и жалкую часть истории в виде stacktrace. Самые продвинутые позволяют сделать лог срабатывания watchpoints с выводом состояния переменных при этом, но это фактически тот же лог (без перекомпиляции).
А для очень многих ситуаций нужна целевая история, включая логи за много шагов назад. Вот поэтому и ставятся всякие printʼы.
И это часто позволяет экономить часы и дни на ручном прохождении.
System.out.println(ex);

Ну и кто-же так делает-то? Всегда же каноничным было ex.printStackTrace();

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

А это следствие дурацких холиворов checked exceptions vs unchecked exceptions. В какой-то момент времени было популярно ругаться на CE вплоть до молчаливого глотания оных. Вот тех, кто такую дурь придумал — надо уважить в первую очередь, а ваш говнокодер возможно и не виноват особо (ну тупо скопипастил с стековерфлоу… ну бывают такие говнокодеры, особенно в начале карьеры… а сейчас он может даже сожалеет об этом… ну или хотябы в UE запихивает эти самые CE, чтобы их выбросило где повыше).

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

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

Отладка кода заведомо сложнее его написания, но почему-то автор не предлагает заменить свою IDE на ed, зато предлагает оказаться от отладчика, потому что он якобы «не оказывает помощи»…
А что имеется ввиду под отладчиком, который можно подключить во время работы? Если у меня только одна ножка процессора доступна со светодиодиком это считается отладчиком или система с недостатком?
Ответ сильно зависит от того, что вы на вашем процессоре делаете.
Если у вас там конечный автомат на десяток состояний, то вы его отлично отладите и так, а если у вас там РТОС на 50 процессов, активно работающая с внешним оборудованием, то система ваша явно с недостатком, т.к. даже на одну ногу можно завести отладочный интерфейс (debugWIRE у Atmel), а если отвоевать еще одну, то хватит на полноценный Test Access Port по cJTAG или SWD.
Во-во. Сначала советуют не использовать отладчики, а потом боятся даже смотреть в код с ассемблерными вставками.
Если посмотреть на профиль автора на SO, то становится понятно, почему за 30 лет работы (неясно откуда взявшиеся, потому что он ВУЗ закончил в 2004 году) он так и не научился пользоваться отладчиками — просто не нужно было, все проблемы решались и без них.
Это не означает, что проблем не было, это всего лишь означает, что эти "проблемы с медведями" решали совсем другие товарищи за совсем другие деньги.
Вообще, большинство подобных статей подразумевают, что речь ведется о enterprise-разработке в вакууме. Априори предполагается, что речь идет о программах, выполняющихся на производительных серверах с большим количеством оперативной памяти, написанных на языках высокого уровня, каких-нибудь веб-сервисах, а остальные типы программ вообще не упоминаются. Поэтому и возникают советы вроде:
Но помните: не следует постоянно изменять данные; создавайте новые элементы с новыми значениями (считайте данные неизменяемыми)
Вроде бы и правильно, но на каком-нибудь микроконтроллере 20 мГц и 64 кБ памяти больно не разгуляешься, а в каком-нибудь видео-кодировщике нужна максимально возможная производительность, и дополнительное копирование памяти тоже как-то не к месту.

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

О чём вам нужно думать, так это о более качественном проекте для вашего кода, о том, как улучшить текущий код. Он нужен для того, чтобы его читали люди. ВСЕГДА. А оптимизациями занимаются компиляторы. Так что вместо использования более коротких слов найдите более толковый способ объяснить в коде, что вы хотите сделать.
Тоже, вроде бы, правильно, но потом у вас в коде обнаруживается тайминг-атака, и приходится использовать битовые операции, чтобы за постоянное время выполнять какие-то манипуляции. А потом появляется Spectre и приходится переходить на вычисления без ветвлений.

И ведь с анонсами технологий такая же ситуация. Встречайте — WebAssembly, теперь можно в браузере делать ВСЁ! Вот, смотрите, мы здесь запустили Doom, а вон там eBay сканер штрих-кодов из C скомпилировал! Читаешь и думаешь: «Охренеть, вот оно, будущее! Наконец-то, по-настоящему кросс-платформенные программы, прямо совсем-совсем без платформозависимого кода! И можно делать ВСЁ! Пойду делать торрент-клиент! Так, постойте, а как открыть TCP-сокет? Никак? Вообще никак? Мда.»

… только отключите комментарии

Ваши дурацкие решения привлекут внимание тех, кто хочет лишь поиздеваться над вами. Например, «это тупо». Кто-то скажет «ты идиот», не понимая, кто же из вас идиот на самом деле.

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

Токсичных и микроагрессоров можно исправить, только если они — это ВЫ

тут какое-то противоречие.

PS: И да, я очень опасаюсь людей, которые на полном серъезе утверждают, что «они не могут исправиться». От таких убеждений всего полшага до «высших мер социальной защиты» (потому что «они же не исправятся, что с ними делать ?»)…
ИХ вы не исправите (пока они сами не захотят)
Вы можете исправить СЕБЯ если осознали что ведете себя как один из них.
Чуть подумав, можно перефразировать так: «жертва принципиального агрессора не может сделать ничего, чтобы изменить модель поведения агрессора. Стимулировать изменение поведения агрессора может либо он сам, либо лица не являющиеся его жертвой. Если возникла коммуникация, в которой вы устойчиво являетесь жертвой, самостоятельно вы можете только дистанцироваться.»

Реально есть и другие варианты, но автор как минимум имеет право на свое мнение.
Спасибо автору! Несомненно эта статья — отражение личного мнения автора, и с ней необязательно соглашаться. Но я согласен практически со всеми тезисами и доводами, так как мой личный опыт к 42 годам научил тому же. :-)
Жаль лишь, что на заре профессиональной деятельности я не имел таких тезисов под рукой.
А на выходе всё тот же самый Therac-25.
Потому что те, кто будут читать ваш код, увидят getUserMessage(userId, true) и будут недоумевать

Можно делать так:
...
let retrieveFullMessage = true
getUserMessage(userId, retrieveFullMessage)
Хорошая статься, автору спасибо. Очень приятно и полезно в работе когда люди с огромным опытом делятся им. И не важно опыт положительный или отрицательный, главное чтобы он был обоснован пусть и субъективно. Всё же это позволяет взглянуть на процесс с иной стороны от теории описываемой в книгах.
Да. Сэкономили нам 30 лет!
Спасибо, интересная статья.
А потом заполните кодом пустоты между комментариями.

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

А здесь ИМХО нужен особый подход.
getUserMessage(userId, true) очевидно плохо.
Нужны константы с осмысленными именами:
const
 retrieveFullMessageFl = true;
 retrieveShortMessageFl = false;

И вызов записывать только с этими константами:
getUserMessage(userId, retrieveFullMessageFl);
getUserMessage(userId, retrieveShortMessageFl);

И вызов записывать только с этими константами
Можно сделать это принудительно, если вместо bool принимать enum.

Очень часто основной приобретаемый навык за N лет работы — желание выдавать субъективное за объективное ввиду попытки оправдать важность этого опыта.


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

Очень часто основной приобретаемый навык за N лет работы — желание выдавать субъективное за объективное ввиду попытки оправдать важность этого опыта.

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

Кстати, заголовок статьи прямым текстом говорит о том, что статья субъективна. Или у меня с Вами разные определения понятий субъективного и объективного?

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

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

Альтернативы, как я понимаю, должен видеть сам читатель. Опять же, читателю стоит понимать, что абсолютной истины не существует, что всегда есть исключения,… Зачем об этом вообще упоминать в контексте «чему Я научился»?

Вы видите, что должны быть альтернативы и исключения — Вы молодéц! Вы относитесь к целевой аудитории! Кстати, если Вы понимаете, что «нигде нет ни альтернатив, ни исключений, а во многих [тезисах] они должны были быть и в немалом количестве», (без сарказма) почему бы Вам о них не написать статью?
Уродское решение: создать новые функции, пометить текущую как нежелательную и добавить sleep в начало функции, чтобы заставлять обновляться тех, кто использует старую функцию.

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


Не смотря на здравые мысли о рабочем процессе, раздел «личное» очень удивляет.
Словарь малопонятных терминов пополняется: к «токсичности» добавились «микроагрессии».
И что это такое — объяснено очень плохо. Чужие неудачные шутки, или проявление неприязни к автору, или всё вместе?
Я почему всё это пишу — меня потрясает эта позиция — убежать от конфликта, спрятаться, уволиться, так ничего и не выяснив. Такая за этим видится беспомощность уровня 5-летнего ребёнка.
А вариантов — почему «микроагрессор» такой «микроагрессор» может быть масса, и правильный можно узнать только у самого человека.
Все случаи не перебрать, отсечём самый неприятный вариант — если вы действительно не нравитесь кому-то, этот человек сам будет вас избегать. Это так работает. И в чём же проблема?
Сильно от ситуации зависит, какую стратегию выбрать — «бей» или «убегай». В некоторых обстоятельствах попытка разобраться с конфликтом может оказаться слишком дорогой в плане времени, нервов или денег (или всего этого вместе), не всегда оно того стоит.
Не соглашусь.
Когда разработчики пытаются решить проблему, иногда они стараются найти такой способ, который решит все проблемы, включая те, что могут возникнуть в будущем.

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

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

Я говорю это к тому, что порой стоит думать наперед при наличии тенденций. Но это, конечно, не задача рядового программиста. Этим занимаются ПМы, аналитики, у кого есть понимание целостного продукта и его перспектив.
И да, с остальным, изложенным в статье, я полностью согласен. В целом статья очень полезная, мне понравилась.
Про середину — лучший вариант.
Но я думаю, что автор и имел ввиду решать явные и конкретные — нужные здесь и сейчас задачи, а не вдаваться в мечтания и угадывание тенденций рынка или чего-то еще из будущего. Ведь действительно часто такое бывает, что сделаешь монстра, гордишься даже что получилась «мега гибкая» «SOLID-ная» система, а потом тебе говорят «Все говно — переделываем».

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

И была CRM система для небольшой компании, — так там на будущее не закладывались сильно. Было тз из двух слов — «ХОЧУ ТАКУЮ ЖЕ». Превратили эти пару слов в 10 листов и не очень закладывались на изменения в будущем. Сделали быстро довольно. Минус правда в этом тоже был. Один из модулей уже через полгода после запуска пришлось переписать на 40% в виду изменений в требованиях пользователей к нескольким фичам нашей системы.

Так что, я тоже склоняюсь к тому что лучше придерживаться золотой середины и Если действительно уверен, что какие-то условия вскоре поменяются, то почему бы не заложиться на них. Опять же, лично мое мнение, что закладываться на будущее можно, если ты хотя бы на 80% можешь сформулировать Тех задание для этих заделов, иначе это просто бред.
Чаще нужна даже не середина, а заранее заложенные небольшие архитектурные решения: где-то впихнуть небольшую фабрику, где-то вынести логику в background поток, где-то наоборот заранее реализовать абстрактного одиночку, проложить шину или порой даже просто вынести отдельную библиотеку.

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

Работа без спецификации хороша при часовой оплате :)


Git add -p хорош тем что вспоминаешь что натворил с прошлого коммита и иногда приходят озарение

Работа без спецификации хороша при часовой оплате :)


Работа без спецификации хороша только при окладе. При почасовой оплате заказчик начинает выносить мозг: я вам уже ХХХ тугриков заплатил, а результата все еще нет!
А вы: типа такой делаем как вы говорите слово в слово, вот 100500 закрытых вами тикета, а вот оплатите пока нам 40 часов.
А тебе в ответ: я говорил совсем не то, то что вы меня не поняли — это ваша проблема, заплачу только когда сделаете и т.д. Плавал, ел, больше не хочу. Как раз при работе на окладе напрямую все чаще заканчивается на списке тасков, багов и реквистов, чем на почасовой.
Жаль, что ради этого пришлось проработать 30 лет
Зарегистрируйтесь на Хабре, чтобы оставить комментарий