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

Senior. Туда и обратно: что я сначала не понимал в своей карьере, а потом как понял

Время на прочтение14 мин
Количество просмотров53K
Всего голосов 88: ↑82 и ↓6+83
Комментарии134

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

В какой момент многие некоторые стажеры сворачивают не туда и из безобидного, но перспектовного Бильбо становятся Голумом? 

Нужна ли для этого сырая пещера? Или хватит «нашей прелести»? 

[Джун] делает функции по 50 строк кода.

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

Другим в таких функциях разобраться сложно.

А джун-то тут причем? Это других надо сдать на курсы.

Можно объяснить на словах, что функции надо дробить на части […]

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

It depends.

Если кусок какого то замороченного кода можно завернуть в функцию и красиво самодокументирующе ее назвать, то почему бы и нет?

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

function pow(base, exp) {
  result := 1
  for i ∈ [0, exp) { result := min(result, base) * base }
}
function pow(base, exp) {
  result := 1
  for i ∈ [0, exp) { result := mult(result, base) }
}
// 100 lines of code
function mult(arg1, arg2) { min(arg1, arg2) * arg1 }

Вы прыгнули по коду, увидели эту конструкцию, она суть умножение, а как мы её используем? — Прыжок назад, удерживая в голове этот код… Когнитивная сложность растет как степень количества вложений.

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

Так вот почему в некоторых легаси-проектах я наблюдаю функции по несколько тысяч строк... А порой просто простыню тысяч на 20 вообще без функций. Оказывается, это чтобы мне разобраться было проще. /s

Хороший пример функции... из 2 строк, которые никто и не требует разбивать. Речь же шла о 50 строках

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

Из которых, возможно, 49 строк комментариев. 

Комментарии не относятся к LOC, так же как и пустые строки.

Прыжок назад, удерживая в голове этот код…

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

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

Если надо одновременно менять код в десятке мест в одной функции на несколько тысяч строк, то радости тоже будет мало.

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

Если надо одновременно менять код в десятке мест в одной функции […]

Это фантазии, не имеющие отношения к дискуссии.

Естественно, у меня один монитор для работы

Не вижу в этом ничего естественного. Это же ужасно неудобно.

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

Это фантазии, не имеющие отношения к дискуссии.

С этими претензиями не ко мне, а к моему оппоненту выше.

Носить с собой на балкон три монитора еще менее удобно.

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

Сколько у вас строк за раз на мониторе помещается?

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

Для контекста мне обычно хватает ±5 строк. Я использую vim, там можно туда-сюда покрутить окно без мыши — не отрывая взгляд от кода.

Я способен удержать в голове контекст

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

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

Что такого интимного в вопроск сколько строк кода помещается на мониторе? И самое главное что в этом более интимного чем у ваших рассказов про то где /как вы работаете?

Ctrl++ — это число можно легко изменить посредством смены размера шрифта

Ну так сколько строк влезет при минимальном удобно читаемом для вас шрифте?

Я использую vim

Это объясняет нелюбовь к декомпозиции.

Тут у меня сразу три вопроса:

  • каким же интересно образом выбор редактора объясняет нелюбовь к декомпозиции?

  • с чего вы взяли, что я как-то особенно не люблю декомпозицию?

  • знаете ли вы, что такое декомпозиция, и чем она отличается от бессмысленного дробления функций на подфункции?

Вижу vim - понимаю что проекты у вас на пару десятков файлов который написали один-два человека. Без нормальной IDE работать с проектами в миллионы строк невозможно

проекты у вас на пару десятков файлов который написали один-два человека

Ух ты, ясновидящий в чате.

Без нормальной IDE работать с проектами в миллионы строк невозможно.

Да ну? Потому что какой-то дурачок в интернетах не умеет, или будут еще аргументы?

по вашему опыту, чего не хватает виму и друзьям?

Просто мне по работе пришлось перейти на VS и я не ощущаю каких либо удобства - скорее наоборот.

Там уже завезли "go to definition", "go to implementation" из коробки? Или там быстрый поиск классов/функций по имени?

Да и вообще IntelliSense в целом заметно упрощает жизнь и ускоряет работу.

Все современные IDE используют Language Servers и Language Server Protocol. Ему (протоколу) вообще безразлично, какой редактор его дёргает. IntelliSense тоже работает поверх него.

А вам, гуёвым, treesitter завезли уже, или ручками плагины устанавливаете, когда надо прочитать файл на экзотическом языке? Дамп какой-нибудь на 15G научились открывать мгновенно? Копипаста с разными буферами работает? В гит кусочек под курсором закоммитить — по-прежнему никак да?

Ему (протоколу) вообще безразлично, какой редактор его дёргает. IntelliSense тоже работает поверх него.

Протоколу может и всё равно. Но при этом разные IDE всё равно поддерживают разный набор фич и работают в этом плане очень по разному.

А вам, гуёвым, treesitter завезли

А вы без оскорблений общаться не умеете?

разные IDE всё равно поддерживают разный набор фич и работают в этом плане очень по разному

Разумеется. И vim в современном мире — гораздо лучше.

без оскорблений общаться не умеете?

Я почему-то наивно полагал, что кириллизованный эпитет, образованный от аббревиатуры GUI (Graphical User Interface), — не оскорбление. Но вот уж воистину — найти, где оскорбиться, — возможно всегда.

Но даже если бы и не умел — как это отменяет тот факт, что ваше облыжное заявление «моя IDE твоя лучше», основанное на невежестве, — неверно в принципе?

Разумеется.

Ну так перечисленные мною конкретные фичи в vim удобно работают?

И vim в современном мире — гораздо лучше.

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

Я почему-то наивно полагал, что кириллизованный эпитет, образованный от аббревиатуры

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

Но даже если бы и не умел — как это отменяет тот факт, что ваше облыжное заявление «моя IDE твоя лучше», основанное на невежестве, — неверно в принципе?

И дальше продолжаете...

Кроме того где я заявлял что «моя IDE твоя лучше»? Человек задал вопрос и я ему конкретно на этот вопрос ответил.

Это уже начинает становиться смешным. Вот заданный вопрос:

по вашему опыту, чего не хватает виму и друзьям?

Вот ваш «ответ»:

Там уже завезли "go to definition", "go to implementation" из коробки? Или там быстрый поиск классов/функций по имени?

Да и вообще IntelliSense в целом заметно упрощает жизнь и ускоряет работу.

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

Согласно моему опыту, преимуществ у других IDE перед вимом нет.

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

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

Если это ответ на заданный вопрос — то я император Китая

Ну похоже вы император Китая.

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

Вы, как "эксперт по vimс, можете просто ответить на мои вопросы? Или вы не в состоянии это сделать? Если нет, то можете просто проходить мимо и я подожду пока ответит человек, на комментарий которого я отвечал.

Вас имело бы смысл оскорбить, если бы я этого хотел, потому что вы первым начали

Я вообще отвечал не на ваш комментарий. На что конкретно вы оскорбились? На слово "завезли"?

в вим этих вещей никогда и не будет.

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

Да и вообще IntelliSense в целом заметно упрощает жизнь и ускоряет работу.

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

А что он предлагает полезного, что не даёт lsp?

Кстати насчёт поиска по файлам, функциям, классам - VS и близко не приближается по скорости и удобству поиска к многим плагинами вима или к helix. По каким-то причинам там fuzzy поиск просто медленнее (resharper вроде быстрее, но тоже не настолько)

UPD: в догонку, а в VS есть jumplist? Такая вещь чтобы например после go to definition вернуться обратно одним хоткеем. Самое близкое что я нашел это bookmarks, но их надо сначала поставить. В helix это есть и это очень удобно при изучении кода. В виме тоже плагины есть наверняка

Это фантазии, не имеющие отношения к дискуссии.

У кого фантазии, у кого регулярная боевая реальность...

А вот проблема о смене контекста при прыгании туда-обратно - это надуманная проблема. Либо человек не освоил свою среду разработки, как следует, либо под язык, на котором он работает, нет IDE, удобно реализующих навигацию по коду - ну хотя бы переход к декларации и определению символа и обратно.

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

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

парадигма, по которой должна быть одна гигантская простыня на тысячи (или десятки тысяч) строк

Не знаю, о чем этот пассаж. Оригинальное число, которое мы тут обсуждаем — 50. И только если это одно атомарное действие. (Это цитата из моего первого комментария, стартовавшего ветку.)

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

Иными словами, вы придумали что-то ортогональное обсуждаемому — и яростно с этим чем-то спорите.

А вот проблема о смене контекста при прыгании туда-обратно - это надуманная проблема.

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

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

Таких IDE в 2025 не существует. Но приоткрою вам завесу страшной тайны: если у вас разительно отличается производительность с IDE и без нее, значит вы решаете задачи, в которых не нужно думать. Потому что задачи, с которыми сталкиваюсь я — требуют провести в редакторе максимум 10% времени, остальное — думать и рисовать на бумажке.

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

если это одно атомарное действие

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

Вы там дальше по своим текстам разносите всяких "коучей" типа Фаулера. Дядя Боб у вас, наверное, тоже нехороший человек. Отсюда и напрашивается впечатление, что ваша "атомарность" это просто оправдание своих простыней.

Но если впечатление ложное - прошу прощения, ошибся.

Таких IDE в 2025 не существует.

С удобной навигацией? Это просто смешно.

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

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

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

Простите, я давно вырос из возраста и ситуации, когда меряются... достижениями. :)

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

Только в другом сообщении вы себе же противоречите:

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

Так способны удержать контекст, или теряете его? Кстати, а держать контекст перед глазами - это не расслабляет и не отучает "загружать контекст в оперативную память мозга" и дальше по тексту? Почему бы не запомнить весь код проекта наизусть? :)

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

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

Таких IDE в 2025 не существует.

Плохо выразился, пардон. Я имел в виду не существует таких, которые не умеют. Просто далеко не все в этих свистопроделках нуждаются.

я давно вырос из возраста и ситуации, когда меряются... достижениями

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

Я уже простынями код пишу, оказывается.

Этого я не утверждал, но было такое впечатление. Значит ошибочное, ещё раз приношу свои извинения. А чего тогда на "коучей" взъелись? У всяких Фаулеров и дядей Бобов, насколько помню, есть предупреждения, что всё хорошо в меру и без фанатизма.

Оригинальное число, которое мы тут обсуждаем — 50. И только если это одно атомарное действие. (Это цитата из моего первого комментария, стартовавшего ветку.)

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

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

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

Диффамация. Вот вам пример на 200+ строк (этим кодом пользуются самые разные люди, которые иногда просят что-то добавить, и если бы этот код был размазан по нескольким хелперам — я бы уже давно сдался и перестал бы что-то добавлять, а так каждое добавление — минут на 15 с тестами).

И зачем то привели пример из 2 строк.

Я его привел для тех, кто сможет экстраполировать. Это называется minimal viable example, если вы не способны — это ещё не значит, что вокруг все такие же.

Максимально неконструктивный троллинг.

Рад стараться.

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

Да уж. Запихнуть прямо в quote столько строк - это полный ппц, даже для миддла. Вы бы книжку "Metaprogramming in Elixir" хоть бы прочитали. Там подробно описано, почему так не надо делать.

Держите рефакторинг, который сокращает ваш говнокод на 51 строку, и при этом читаемость возрастает существенно. Плюсом ещё и ошибку вам исправил при доставании syntax из options, и спеки для статического анализатора добавил. И тесты, разумеется, на отдельные небольшие функции писать гораздо проще, чем на одну огромную.

  defmodule ASTHelpers do
    @spec fetch_syntax(keyword() | map()) :: Finitomata.Mermaid | Finitomata.PlantUML
    def fetch_syntax(options) do
      case Keyword.fetch!(options, :syntax) do
        :flowchart ->
          Finitomata.Mermaid

        :state_diagram ->
          Finitomata.PlantUML

        module when module in [Finitomata.Mermaid, Finitomata.PlantUML] ->
          reporter().info([
            [:yellow, "deprecated: ", :reset],
            "using built-in modules as syntax names is deprecated, please use ",
            [:blue, ":flowchart", :reset],
            " and/or ",
            [:blue, ":state_diagram", :reset],
            " instead"
          ])

          module

        invalid_value ->
          raise ArgumentError, "Invalid value of syntax opt: #{inspect(invalid_value)}"
      end
    end

    @spec fetch_listener(keyword() | map(), atom()) :: Finitomata.Listener.t() | Mox.t()
    def fetch_listener(options, module) do
      mox_envs = options |> Keyword.fetch!(:mox_envs) |> List.wrap()

      case Keyword.fetch!(options, :listener) do
        :mox -> if Mix.env() in mox_envs, do: def_mock_for(module)
        {:mox, listener} -> if Mix.env() in mox_envs, do: def_mock_for(module), else: listener
        {listener, :mox} -> if Mix.env() in mox_envs, do: def_mock_for(module), else: listener
        listener -> listener
      end
    end

    defp def_mock_for(module) do
      with {:error, error} <- Code.ensure_compiled(Mox) do
        reporter().info([
          [:yellow, "expectation: ", :reset],
          "to be able to use ",
          [:blue, ":mox", :reset],
          " listener in tests with ",
          [:blue, "`Finitomata.ExUnit`", :reset],
          ", please add ",
          [:blue, "`{:mox, \"~> 1.0\", only: [:test]}`", :reset],
          " as a dependency to your ",
          [:blue, "`mix.exs`", :reset],
          " project file (got: ",
          [:yellow, inspect(error), :reset],
          ")"
        ])
      end

      [module, Mox] |> Module.concat() |> tap(&Mox.defmock(&1, for: Finitomata.Listener))
    end

    defp reporter do
      if Code.ensure_loaded?(Mix), do: Mix.shell(), else: Logger
    end
  end

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

  defp ast(options, schema) do
    quote location: :keep, generated: true do
      options = NimbleOptions.validate!(unquote(options), unquote(Macro.escape(schema)))

      require Logger

      use Telemetria.Wrapper

      alias Finitomata.Transition, as: Transition
      import Finitomata.Defstate, only: [defstate: 1]

      @on_definition Finitomata.Hook
      @before_compile Finitomata.Hook

      syntax = Finitomata.ASTHelpers.fetch_syntax(options)
      listener = Finitomata.ASTHelpers.fetch_listener(options, __MODULE__)
      shutdown = Keyword.fetch!(options, :shutdown)
      forks = Keyword.fetch!(options, :forks)
      auto_terminate = Keyword.fetch!(options, :auto_terminate)
      hibernate = Keyword.fetch!(options, :hibernate)
      cache_state = Keyword.fetch!(options, :cache_state)
      persistency = Keyword.fetch!(options, :persistency)

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

Я его привел для тех, кто сможет экстраполировать. Это называется minimal viable example, если вы не способны — это ещё не значит, что вокруг все такие же.

Your hobby is extrapolating
Your hobby is extrapolating
Your hobby is extrapolating

Ну, видите, как интересно. Более реальный пример наглядно показал, что вы пока что просто плохо умеете программировать. Желаю вам в этом году повысить свой профессиональный уровень, а то подрываете мне тут имидж программистов на Elixir. Ая-яй-яй.

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

когда я опции разбираю, я хочу видеть […]

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

И да, МакКорд ничего про такой код в «Metaprogramming Elixir» не писал (да и не мог), потому что книжка вышла 10 лет назад, когда весь код финикса выглядел именно вот так (а уж экто в те времена — вообще одна сплошная радость).

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

так что ваши неуклюжие попытки затруднить мне ее развитие — идут прямо в корзину

Понятно, по существу сказать то и нечего xD

ей люди, знаете ли, пользуются;

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

И да, МакКорд ничего про такой код в «Metaprogramming Elixir» не писал (да и не мог), потому что книжка вышла 10 лет назад

Вот уж наглядная демонстрация выражения "смотрю в книгу - вижу фигу". Перечитайте:

Avoid Injecting Large Amounts of Code
Avoid Injecting Large Amounts of Code

И дальше как раз идёт minimal viable example как из плохого кода по типу вашего сделать приличный код.

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

Жаль вас, ни разу в нормальной компании не довелось поработать. Структурирование кода - это важный навык для любого программиста.

А то принимаете любой атом в качестве syntax, а пользователи ваши потом с дебагом маются […]

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

ни разу в нормальной компании не довелось поработать

В компании может и не довелось, но у меня такое количество коммитов в корку эликсира, и почти во все библиотеки dashbitco, что «над одним кодом» — немного доводилось.

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

Хотели сказать "незадокументированную" xD

Ни в самом коде, ни в README нет ни явного указания на кастомный синтаксис, ни примеров его создания. Просто по сути ещё один аргумент накинули, почему ваш код плох - содержит незадокументированные и не покрытые тестами "возможности".

у меня такое количество коммитов в корку эликсира

Ну, раз начали понтоваться, то пишите уж ваш ник на Github - посмотрим, как вы в корку эликсира функции по 50+ строк пропихивали. А то пустое сотрясание воздуха.

В README? В README нет, факт. В документации, правда, есть, конечно. «Пример создания кастомного синтаксиса» — эта фраза сделала мой день просто, да.

раз начали понтоваться

Понтоваться? Да упаси господи, вот еще, бисера на всех не напасешься. Просто упомянул, что ну доводилось с неплохими разработчиками вместе над кодом работать.

как вы в корку эликсира функции по 50+ строк пропихивали

Это-то тут причем? Я в чужие монастыри (в отличие от, например, вас) со своим калашным рылом и доморощенным уставом не хожу. Да там и без меня справляются. Хотя Жозе в последнее время и делает всё, чтобы эликсир стал больше походить на голанг, чем на эрланг. Хотя бы от мутирующих по месту переменных, как в питоне, нам удалось его отговорить, хотя подавляющее большинство людей там были вашего уровня компетентности, и все — как один — за.

Мой ник довольно несложно найти, да и я его никогда не скрываю особенно (например, когда даю ссылку на код, да), но вы своими по-детски надутыми щёчками и мидловской супер-уверенностью в своей правоте сделали все, чтобы именно вам пришлось его искать самому. Ну, или не искать. Мне пофигу.

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

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

Чтобы проводить ликбез необходимо чем-то подтвердить свой авторитет, для начала, облыжных заявлений и никчемных якобы «правок», которые портят чужой код — недостаточно. А подтвердить-то внезапно и нечем, хо-хо-хо.

Я вам фрагмент из книги предоставил, в котором прямым текстом написано, что ваш подход к структурированию кода является типичной ошибкой. При этом вы самонадеянно утверждали, что там не может быть такого написано. Но признать, что вы облажались, у вас силы духа не хватает. Вот и пытаетесь нелепо съехать с темы, переходя на личности. Это ещё один тупой мув в стиле джуна, потому что вы обо мне ничего не знаете. И выглядите во всей этой ветке максимально тупо и нелепо xD

выглядите во всей этой ветке максимально тупо и нелепо

На том и порешим.

С этим бессмысленно спорить.

Деревья синие. С этим бессмысленно спорить.

Вы думаете глазами, что ли?

У кого фантазии, у кого регулярная боевая реальность...

Увы, мы не можем определить, фантазии это у вас или реальность. Раз проектов своих вы не показываете, видимо, фантазии - вы на это так витиевато намекали?

Увы, мы не можем определить, фантазии это у вас или реальность.

И не надо.

Раз проектов своих вы не показываете, видимо, фантазии - вы на это так витиевато намекали?

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

То есть вы настойчиво советуете то, что сами не делаете. Не иначе, от конкурентов так избавиться решили?:)

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

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

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

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

Вы утверждаете, что каждую строчку или несколько строчек решения надо вынести в отдельную функцию с десятками параметров?

Вы читаете мысли? Где я такое утверждал?

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

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

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

Бывает так, что эти длинные линейные портянки - вся или почти вся бизнес-логика (типовой пример)? Или есть архитектура, где эти портянки изолированы в "вычислительном ядре", а остальной код занимается всеми другими типовыми задачами - всевозможными вводами-выводами, реализацией всяких API, интерфейса CLI, графических интерфейсов, сбором данных, построением статистики и чего там ещё бывает в типовых системах?

Могу на очередной лад повторить - инструменты следует применять без фанатизма и по назначению. Конечно, если насильно каждую строчку загонять в функцию, и вдогонку давать этой функции вводящее в заблуждение название, то от этого будет только плохое. Но весь этот холивар тут реально выглядит уже так: "Молоток ударил по пальцу! Молоток (и инструменты вообще) это чистое зло, а те, кто всё это придумал - кретины, предавшие человечество!!11"... :)

Ну .. кретинов в ИТ как раз хватает, лет на 100 припасено.. :)

Типовый?

Тред начинается с сообщения "Откройте код реализации любого более-менее сложного алгоритма, хотя бы.", вот об этих алгоритмах мы и говорим.

Вот прямо вся бизнес-логика состоит из решения вот таких уравнений?

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

Вообще, приведите конкретный пример...

Вот вам пример, мой открытый проект на гитхабе с популярным процессором спутниковой интерферометрии: https://github.com/AlexeyPechnikov/pygmtsar Можете посмотреть аналоги от НАСА и Европейского космического агентства, которые решают те же уравнения :)

А вот вам от сотрудника НАСА модно-стильно-молодежно на классах и с разбиением где ни попадя на функции код: https://github.com/ASFHyP3/burst2safe Раз вы такой уверенный советчик, вам будет нетрудно найти в моем коде аналогичный функционал, причем на каждые 100 килобайт "модного" кода у меня получается примерно сотня строчек. Попробуйте в этом вот модном коде найти самые очевидные баги - а если найдете, то понять, как их исправить, не переписывая весь код. Замечу, что эти баги делают код абсолютно бесполезным (просто абсурдным, учитывая последствия его запуска).

А пока это сферический конь, не более.

Э-э-э, вы сами никогда код не писали? Так зачем тогда обсуждаете...

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

Просто наблюдение, выводов не будет :)

против «декомпозиции ради декомпозиции»

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

люди, которые не стесняются показывать код (и он у них в избытке есть)

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

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

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

Даже не знаю, с чего начать.

  • мне за мой «говнокод» платят, есть гипотеза, что уж никак не меньше, чем в «хайтеках»; я просто отказываюсь работать там, где легко отчуждаемый код (не имеющий отношения к бизнес-логике) покрывается NDA просто потому, потому что хрен знает почему

  • вечером нужно отдыхать, спору нет, я именно так и делаю; а также утром, днём, и в любое время, когда писать код мне неохота

  • ЧСВ — это вы о наболевшем, наверное, вообще не понятно, как оно возникло в дискуссии

  • пара лишних копеек меня лично уже давно не интересует в принципе

из того, что почитал я у вас с соратником

Да, мне тоже тексты на суахили не особо. В редакции моего уютного бложега они бы редактуру не прошли.

этот код не прошёл бы ревью в фирмах, где я работал и работаю

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

Просто задам вопрос: а вы в этих ваших хайтеках используете докер, или там кубернетис?

Разумеется. А ещё "у нас есть такие приборы, но мы вам о них не расскажем" (с) - кучу всего используем.

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

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

Поясню. Типичный случай (в моём опыте) - одновременно существуют легаси системы и параллельно с ними разрабатываются новые. Последнее происходит потому, что легаси хорошо выполняли свои задачи на ранних стадиях стартапа, но плохо справляются с темпами роста. На ранних стадиях обычно достаточно хорошие по оплачиваемой функциональности прототипы ради экономии времени волшебным образом превращаются в продакшен. Далее происходит быстрый рост всего - и довольно быстро оказывается, что легаси система с сотнями тысяч строк кода и функциями от сотен до десятков тысяч строк крайне плохо масштабируется на новые запросы. Увеличивается количество клиентов и обнаруживаются баги - и начинается бомбёжка тикетами, с которыми не справляется техподдержка. Увеличивается количество клиентов - и быстро растёт необходимость внедрения новых фич. И это не говоря уже о том, что подобный код крайне трудно адаптировать к горизонтальному масштабированию. Баги, фичи, скорость - всё это до определённой меры относительно быстро могут выполнять люди, изначально, извиняюсь, нахерачившие вот это всё. Пока они работают в фирме - они лидеры, т.к. это часто не столько программисты, сколько инженеры или учёные, реализующие свои - да, часто практически гениальные - идеи. Эти гениальные люди не умеют и/или не хотят разрабатывать код так, чтобы снижать стоимость входа для новых разработчиков. И они продолжают херачить как умеют. В какой-то момент, т.к. темп растущего бизнеса очень напряжённый, они выгорают и тем или иным образом уходят. Часто, толком не успев подготовить хотя бы одного сменщика (лично был знаком с системой, для высокоуровнего детального понимания работы которой (top-down), применимого в коде, нужно года два практически работать с ней в основном в режиме отладки (bottom-up) - нет человека, который бы мог или был бы готов провести адекватный онбоардинг).

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

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

Нет, конечно, в книжках же написано, что докер — это хорошо.

Вы зачем-то путаете две совершенно разных ситуации. Одна - использовать инструмент. Другая - поддерживать работу и разработку системы. В первом случае вообще всё равно, что там в кишках у инструмента - пусть хоть говно мамонта. Если надёжно работает и выполняет свою задачу, конечно. Компании с достаточно большими инвестициями могут себе позволить достаточно эффективно поддерживать даже окаменевшие каки динозавров. Моя история выше - это про относительно успешные стартапы, но на этапе до (опционального) превращения в единорогов.

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

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

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

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

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

Простите, но если мы вернемся к моему коду — то он и есть та самая библиотека, которую все используют, не глядя в код. Более того, верхний уровень, сиречь API, — создает буквально минимальную когнитивную нагрузку из всех известных мне имплементаций FSM с сопутствующими гарантиями (не путать с флагом в БД, который принято выдавать за имплементации конечных автоматов в современных реалиях). За чужой код отвечать не готов.

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

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

какие паттерны вас покусали? Роберт Мартин лично хлестал по щекам

Я выше ответил уже, в принципе. В мире не существует книги, которая принесла бы больше вреда в индустрию, в сравнении с «Clean code». Если обращаться с коллегами, как со стадом тупых баранов, — в конечном итоге они и превратятся в баранов (что мы и наблюдаем en masse). Го создавался таким уродливым намеренно («чтобы дебилы ничего не могли попортить», да).

Если вы отвлечетесь от вытравленных кислотой в камне рекомендаций авторитетных распиаренных ноунеймов (что нахрен такого написал в своей жизни Мартин, что дало ему право говорить «как надо»?) — и сравните свои ощущения от понимания 50 строк написанных последовательно от 50 строк (+ ±30 добавленных заголовков функций и т. п. мусора), разбросанных по файлу(-ам) — вы можете внезапно прозреть (а можете и остаться при своем мнении, я не возражаю).

Почему-то романисты (кроме Кортасара и отчасти Паланика) не выносят отдельные главы романа в отдельные подкниги, а фигачат подряд. Как думаете, почему?

Простите, но если мы вернемся к моему коду ...

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

Просто такой подход работает не везде - и это тоже совершенно нормально, что в кровавом энтерпрайзе другие подходы, куда более ориентированные на текучку кадров и на потребность в максимально быстрой реакции на происходящее. При этом объёмы кода таковы, что даже самые крутые и опытные спецы (которые способны умещать у себя в голове кучу логики, а ещё и часто доктора и профессора по информатике и прочим точным дисциплинам, т.е. априори далеко не глупые люди) очень ценят лаконичность и выразительность. Например - иногда потратить 15-20-30 и более минут времени на подбор подходящего имени для символа (переменной, функции, класса и т.д.) это нормальная история. Вы знаете, как трудно бывает найти специалиста и по используемым языкам, и по сопутствующим технологиям, и по предметной области? Часто практически невозможно, и бизнесу приходится идти на компромиссы по навыкам. И чтобы новые люди могли начинать приносить пользу в коде с минимальным временем обучения - просто необходимо относиться к коду с максимальной щепетильностью. Хех., у меня уже лет десять практически во всех IDE и редакторах включено отображение всех видов whitespace, это уже на уровне профдеформации.

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

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

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

В мире не существует книги, которая принесла бы больше вреда в индустрию, в сравнении с «Clean code».

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

Я про Фому, вы мне обратно — про Ерёму. Даже в кровавом ынтерпрайзе есть отчуждаемые куски вне бизнес логики. Они должны становиться библиотечным кодом. Желательно, открытым (так проще и быстрее отлавливаются дикие корнер-кейсы, наподобие Польских версий Виндоуз™). Практика показывает, что очень часто ынтерпрайз, поставленный перед фактом «или это в ОСС, или до свидания» — начинает хотя бы чуть-чуть лежать навстречу.

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

С тем, что «гуглерам» проще наоборот — я не только никогда не спорил, но и сам высказывал эту мысль триста тысяч раз (или около того).

наверняка подразумевали и/или «Clean Architecture»

Нет, я подразумевал именно то, что написал — застарелая привычка говорить строго то, что думаю. С «Clean Architecture» — сложнее, я её бегло пролистал, а говорить о вещах, в которых не чувствую себя уверенно — не мой конёк. Она, наверное, помогает лидам выстроить работу с командой «гуглеров» — допускаю. Но я говорил про пишущих код и про читающих код, а не про функционеров, которыми лиды и являются по сути. Просто параллельно есть такая ветка развития Principal → Staff → Fella, куда идут люди, любящие писать код, а не делать ревью…

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

Есть авторитетные люди от мира Computer Science (Joe Armstrong, например, Lennart Augustsson, там, John Hughes). А есть Мартин и иже с ним — кто он нафиг такой? — Да хрен его знает. Писатель. Советует оболванивать «гуглеров», чтобы ими легче было управлять, и чтобы они дров не наломали. Как говаривал в свое время по иному поводу Линус Торвальдс — «Talk’s cheap, show me the code».

Мне доводилось работать с кодовыми базами на 30М строк на Коболе, с монолитными динозаврами на Руби, с чужим закрытым кодом с ужасным интерфейсом на Джаве, я в 2001 году AST парсил на Хаскеле, когда про Хаскель кроме Аугустассона и Хьюза вообще никто не знал. Мне доводилось видеть такие кодовые базы, что у меня испортилось зрение и появились хрипы в лёгких. И вот на основе всего вот этого багажа — я пришел к мнению, что читать сверху вниз одну книгу удобнее, чем открывать закладки на каждый абзац — сразу в тридцати.

Я это мнение никому не навязываю, впрочем. Как блистательно сформулировал в своё время Сомерсет Моэм:

If in the following pages I seem to express myself dogmatically, it is only because I find it very boring to qualify every phrase with an 'I think' or 'to my mind'. Everything I say is merely an opinion of my own. The reader can take it or leave it. If he has the patience to read what follows he will see that there is only one thing about which I am certain, and this is that there is very little about which one can be certain.

The Summing Up

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

Это для кого это типовой пример? Для разработчиков Maple или Wolfram Mathematica?

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

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

Суть в том, что написание математических библиотек - это очень узкий кейс. Называть его типовым крайне странно, т.к. 99.9% программистов такое не пишут вовсе.

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

Программисты как раз пишут алгоритмы, а кодеры кодят бизнес-логику. Это как разница между инженером и техником.

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

А почему одно должно обязательно исключать другое? Бизнес-логика не может содержать алгоритмы? Серьёзно?

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

Это крайне наивный взгляд)

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

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

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

про абстракции это хорошо, когда к месту, но вот задачка из жизни - предположим есть bsp на новую evaluation board, примерно 20К файлов, но все для Linux 2.6.x, требуется porting на более новую версию, например 6.0, какие уровни абстракции Вы видите?

это к тому что примерно с такими задачами приходилось иметь дело за 30+ лет работы в us, а так конечно приятно было бы переписать с нуля используя абстракции, инкапсуляцию и пр., только время на всю работу всего 1-2 месяца, потому что люди ждут, еще придется делать интеграцию и пр.

Я всю жизнь работаю за ноутбуками с одним монитором. Самый удобный сплит скрин имхо у VScode. Однако, при "путешествии" по стеку референсов два монитора и не нужны. В VScode достаточно навестись на класс и нажать сочетание клавиш, чтобы открыть фрейм со списком всех референсов функции/метода, класса и т.д.

В общем, не в мониторах дело.

А чем сплит в VSCode вот так особенно лучше консольных вариантов (vim, emacs, да просто tmux)?

Имел ввиду из IDE имеющих GUI и опять же это ИМХО. Я использовал много IDE с GUI за свою жизнь и лично для меня удобней всего оказалась VS code, потому что сплит скрин у неё выглядит удобным. Причём даже удобнее чем в обычной VS с которой работал довольно много в своё время.

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

Жуть пишете. Если коллеге тяжело удерживать контекст и поэтому он пишет лапшу - пусть учится абстракциям. Или лучше вообще его уволить. Потом же дорабатывать будет нельзя, связанность в лапше всегда запредельная, такие коллеги ведь заодно и область видимости ограничить не могут, у них переменная с самого начала до конца может тянуться, через тысячу строк.

поэтому он пишет лапшу

Откуда взялась лапша? Была же вроде просто функция на 50 строк, про лапшу никто не говорил. Вот что вики говорит про первое употребление:

In a 1980 publication by the United States National Bureau of Standards, the phrase spaghetti program was used to describe older programs having "fragmented and scattered files".

Fragmented and scattered — это как раз про раздробленные на вагон маленьких функций, ага.

такие коллеги ведь заодно

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

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

Однако ваша ast не атомарна, отказ выделить даже простую fetch_syntax мне не ясен. Вероятно это ваши личные предпочтения, но читабельность страдает, работать в команде с таким кодом сложнее. Если работаете один, а не в команде, пишите, как вам удобно.

отказ выделить даже простую fetch_syntax мне не ясен

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

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

Моя ast как раз атомарна: она делает ровно одну вещь, парсит параметры и инджектит их, эти параметры, в код. Авторитетом меня задавить очень сложно: ну Крис переобулся под натиском Жозе, да и Жозе сам переобулся, и теперь они продавливают идеологию Роба Пайка: нам нужен такой язык и такие туториалы, чтобы даже дубовое полено не накосячило. Бог им в помощь, за ними вон стадо таких, как мой оппонент выше, в рот заглядывают, авторитетом упиваются.

Если работаете один, а не в команде, пишите, как вам удобно.

Спасибо, век такой милости не забуду.

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

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

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

Хуже для кого? Для читающего - да. Разница между "книгой" в 50 строк и "прыганьем" в том, что и там и так получается книга, но первая - без оглавления

А джун-то тут причем? Это других надо сдать на курсы.

Курсы чего? Разбирания в сложном коде? Обычно как раз учат писать легкоразбираемый код, а не писать сложный и потом в нем разбираться. Зачем одноу разрешать создавать проблему и учить всех остальных ее решать, вместо того, чтобы просто не создавать проблему?

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

Алгоритм, используемый миллионами людей делается максимально эффективным и каждая наносекунда важна, целью разработки не стоит задача "чтобы все сразу поняли как все устроено", поэтому там допустимы функции и по 200 строк. Ровно противоположная ситуация в компаниях - зачастую (не всегда) не нужно гнаться за максимальной производительностью, а нужно укладываться в SLA, а в остальном делать упор, например, на возможность поддержки, чтобы в будущем сэкономленная наносекунда не превратилась в тысячи потраченных человеко-часов на функцию, в которой никто не может разобраться

Потрясает, конечно, как люди дискутируют с тараканами в собственных головах.

Вот мой посыл, внятно изложенный:

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

Вы видите тут апелляцию к производительности? А её нет. Тут есть апелляция к внятности кода.

В другой ветке:

Хороший пример функции... из 2 строк, которые никто и не требует разбивать. Речь же шла о 50 строках.

Конечно же я не удивлен, что вы не знаете, что такое обобщение и при чем тут выделение образца. Shrinking — наверняка тоже пустой звук, бывает.

———

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

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

Вы видите тут апелляцию к производительности? А её нет. Тут есть апелляция к внятности кода.

Вы не понимаете о чем я вам говорю. Функции делают по 1000 строк в популярных алгоритмах ради высокой производительности. Это я вам объясняю причину, почему приводить в пример их некорректно. Здесь не играет никакой роли читаемость кода. Если нужно будет увеличить функцию с 100 строк до 1000000, при этом она начнет работать на наносекунду быстрее - именно это разработчики алгоритма и сделают и им будет наплевать, что никто не будет понимать как все работает. Им наплевать на поддержку (условно). В компаниях же ровно обратная ситуация - поддерживаемость кода зачастую играет ключевую роль. Будь хоть идеален ваш код, но если он не понятен, пускать его в продакшн - значит обрекать себя в будущем на огромные затраты по его поддержке.

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

У вас с коучами кстати логическа ошибка, называется "ложная аналогия". Даже если бы о необходимости разбивать функции говорил Гитлер, это вовсе не значило бы, что можно было бы приводить как аргумент "это сказал Гитлер"

Вы не понимаете о чем я вам говорю.

А зачем мне понимать ваш внутренний монолог с вашими тараканами?

Еще раз, для особо одарённых.

  • Откройте код реализации любого более-менее сложного алгоритма (просто откройте код, не думайте, зачем он такой, просто посмотрите на него и постарайтесь его понять).

  • Подробите его на кусочки — и попробуйте его понять снова.

  • Станет сложнее.

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

У вас с коучами кстати логическа ошибка, называется "ложная аналогия".

Аналогия? Вы на грибах, что ли, сидите? Причем тут вообще аналогия? Вот мой силлогизм:

Коучи (типа Фаулера, больше него вреда своими идиотскими посылами не принес вообще никто в индустрии) учат писать функции по три строки ⇒ дурачки ведутся. Всё. Никаких аналогий.

А зачем мне понимать ваш внутренний монолог с вашими тараканами?

Если кажется что у людей вокруг тараканы в голове, то вероятно тараканы не у них

  • Откройте код реализации любого более-менее сложного алгоритма (просто откройте код, не думайте, зачем он такой, просто посмотрите на него и постарайтесь его понять).

  • Подробите его на кусочки — и попробуйте его понять снова.

  • Станет сложнее.

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

Аналогия? Вы на грибах, что ли, сидите? Причем тут вообще аналогия? Вот мой силлогизм:

Коучи (типа Фаулера, больше него вреда своими идиотскими посылами не принес вообще никто в индустрии) учат писать функции по три строки ⇒ дурачки ведутся. Всё. Никаких аналогий.

Есть коучи, которые учат не курить. Получается те кто слушает их и бросает дурачки? И после этого вы говорите про тараканов)) "Грибы" кстати называются логикой, хоть иногда рекомендую употреблять в пищу

Если код раздробить на кусочки с умом, то в большинстве случаев он будет понятен. Вы хотите сказать, что из 50 строк кода вы не сможете в слух сказать "в строках 1-5 делаем то-то, в 6-12 мы проверяем то-то и т.д"? В сложном алгоритме такое может случиться, однако сложные алгоритмы это обычно редкость. Назовите метод или функцию нормальным именем и все будет разбиваться и читаться прекрасно.

Конечно, как уже сказали выше it depends - есть случаи, когда кусок кода лучше не разбивать. Очень редко мне приходится так делать. Но чаще всего 50 строк кода это уже цепочка функционала, которую можно разбить для удобства и/или переиспользования фрагмента

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

Про всё остальное я тысячу раз уже сказал: читать сверху вниз удобнее, чем две строки тут, потом пять там, потом опять две тут, потом вон еще пять — в другом файле. В литературе есть ровно один пример романа, написанного таким хитрым способом («Игра в классики» Кортасара, если вы зачем-то изучали питон вместо мировой литературы) — и я в свое время потратил много сил, опрашивая знакомых и просто случайных людей, кто не поленился прочесть «С других сторон». Среди примерно пары сотен опрошенных — таковых оказалось 1 (один).

«Цепочка функционала» никак не выигрывает от введения новых бесполезных сущностей.

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

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

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

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

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

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

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

Предположим, что есть 50 строк кода, которые выполняют 5 семантически изолированных операций...

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

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

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

спутник по орбите с известным вектором ...

Алексей, поскольку Вы знакомы с предметом, позволю задать вопрос чуть в сторону, предположим у Вас есть измерения с известной ошибкой (например матрицей ковариаций), требуется найти именно этот самый вектор + его матрицу ковариаций, как Вы могли бы это сделать в реальном времени?

кстати какой именно вектор выбрали бы?

возможно это будет интересней чем обсуждение декомпозиции и архитектурных паттернов :)

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

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

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

Переиспользование — однозначно да.

Есть исключение: когда логика в двух местах совпала по абсолютной случайности. Главный симптом — невозможность придумать сколь‑нибудь вменяемое название функции.

В остальном с вашими тезисами согласен.

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

Многие в начале увлечения программированием без задней мысли пишут спагетти‑код с наибольшей низкоуровневой сложностью. Но потом некоторые, почитав Фаулера и дядю Боба (и не донца поняв мотивы их принципов), кидаются в противоположную крайность — натягивают проект на какую‑нибудь хайповую архитектуру как сову на глобус, так что сложность архитектуры начинает доминировать над проектом и приводить контрибьютеров в состояние склонных к насилию психопатов.

Функции делают по 1000 строк в популярных алгоритмах ради высокой производительности.

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

Ой, вы так изящно ругаетесь! Инлайн, макросы!..

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

А макросы, блоки кода и т.п. это ж скакать по коду нужно, а то и в другой файл!

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

Касаемо разбиение функций и методов могу добавить, что бред делить код по количеству строчек. Код делится не по строчкам, а по смыслу. Хорошо написанная функция будет понятна всем программистам вне зависимости от её размера.

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

Так за здравие начали, и вдруг — бабах, SOLID, который сам по себе в вакууме — лютая инфоцыганщина (как и всё, что вышло из-под пера Дедули «Теоретика» Боба).

  • SRP — единственный разумный принцип из пяти (в формулировке «одна сущность кода обязана отвечать за одну сущность предметной области») — откуда, кстати, напрямую следует, что дробить функции на недофункции — противоречит этому самому SRP, которым так любят размахивать адепты лапши из бесконечного числа малюсеньких хелперов

  • OCP — конфиги такие: «да, да, пошли мы нахер»

  • LSP — вообще умора, на языках с классами свет клином не сошелся (если оно про полиморфизм — так и говорите, не нужно людей путать)

  • ISP — никогда не мог понять вообще, о чём это (если я не использую что-то, я от него по опредению не завишу, ну)

  • DIP — ну ладно, implementation details действительно не нужно выпячивать наружу, но dependency injection гораздо глубже и важнее, чем интерфейсы

Ох уж это пагубное стремление заковать живое (в данном случае — разработку кода) — в какие-то нафиг паттерны на все случаи жизни, дать каждому своё название, объединить все это красивым акронимом, посолить, поперчить… Мир устроен сложнее, паттерны работают только на обезьянних работах, типа крудов и блокчейнов, стремление загрести под одну гребенку всё разнообразие — всегда выдает человека неумного и далекого от реальности (каковым Мартин и является).

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

Откуда столько агрессии-то? Мартин с Фаулером в детстве конфеты отбирали после школы? Банда четырёх потом отнимала мелочь в тёмном переулке и давала подзатыльники? Как так вышло, что слова и сокращения типа "паттерны" и "SOLID" стали для вас эмоциональными триггерами? Или вы реально замеряли IQ Мартину и он оказался ниже вашего? И даже это не повод говорить об этом публично, но раз уж начали - приведите хоть какие-то доказательства. Пока в ваших сообщениях есть толика трезвости (декомпозицию, как и всё, нужно использовать без фанатизма) и море негативных эмоций с возведением в абсолют.

Код делится не по строчкам, а по смыслу. 

Это безусловно так. Но случаев когда единый смысл занимает много строк - редки. Поэтому условный N используется в таком варианте: у тебя получилась функция из N+ строк, а точно ли она одно атомарное действие совершает или ты сам себя обманул?

Если действительно одно атомарное действие, то и ok. Но в 99.9% случаев это окажется не так при достаточно большом N (напр. 50).

Откройте код, скажем, библиотеки OpenCV и посмотрите размеры функций.

И как это противоречит тому, что я написал?

Во-первых, это библиотека с кучей математики. Во-вторых, ещё и на чудовищно многословном С++.
Ну ok, я уточню, математические библиотеки на С++ не пишут 99.9999% программистов

Зачем вы берёте такой махровый edge-кейс и пытаетесь его представить как нечто типовое - это загадка, конечно.

Это типовая библиотека алгоритмов, ровно как мы и обсуждаем.

Почему для примера вы используете тот самый 0.1%?

Примерно все библиотеки алгоритмов такие, так что ближе к 100%.

получилась функция из N+ строк, а точно ли она одно атомарное действие совершает или ты сам себя обманул?

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

    public function login(ServerRequestInterface $request): ResponseInterface
    {
        $params = $request->getParsedBody();

        $isValidParameters = $this->validator->isValid($params, [
            'username' => 'required|string',
            'password' => 'required|string',
        ]);

        // Validate request parameters
        if (!$isValidParameters) {
            return $this->responseFactory->createJsonResponse(
                400,
                ['error' => 'Invalid request parameters']
            );
        }

        // Extract credentials
        $username = $params['username'] ?? '';
        $password = $params['password'] ?? '';

        // Authenticate user
        $authResult = $this->authService->authenticate($username, $password);

        if ($authResult->isSuccess()) {
            return $this->responseFactory->createJsonResponse(
                200,
                ['message' => 'Login successful', 'token' => $authResult->getToken()]
            );
        }

        return $this->responseFactory->createJsonResponse(
            401,
            ['error' => 'Invalid credentials']
        );
    }

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

Чтобы сократить код мы можем разделить метод на несколько более мелких (например поместить валидатор в отдельный прайват метод), за счёт чего получить целевой метод, занимающий в 2 раза меньше строчек кода. Но какой ценой? Мы создаём абстракцию на абстракцию, усложнем восприятие кода, повышаем цикломатическую сложность, создаём проблемы при покрытии тестами. Вот пример кода с разделением на методы:

    public function login(ServerRequestInterface $request): ResponseInterface
    {
        $params = $request->getParsedBody();

        if (!$this->validateRequestParameters($params)) {
            return $this->invalidParametersResponse();
        }

        $username = $params['username'] ?? '';
        $password = $params['password'] ?? '';
        $authResult = $this->authenticateUser($username, $password);

        return $authResult->isSuccess()
            ? $this->successfulAuthenticationResponse($authResult->getToken())
            : $this->invalidCredentialsResponse();
    }

    private function validateRequestParameters(array $params): bool
    {
        return $this->validator->isValid($params, [
            'username' => 'required|string',
            'password' => 'required|string',
        ]);
    }

    private function invalidParametersResponse(): ResponseInterface
    {
        return $this->responseFactory->createJsonResponse(400, ['error' => 'Invalid request parameters']);
    }

    private function authenticateUser(string $username, string $password)
    {
        return $this->authService->authenticate($username, $password);
    }

    private function successfulAuthenticationResponse(string $token): ResponseInterface
    {
        return $this->responseFactory->createJsonResponse(200, ['message' => 'Login successful', 'token' => $token]);
    }

    private function invalidCredentialsResponse(): ResponseInterface
    {
        return $this->responseFactory->createJsonResponse(401, ['error' => 'Invalid credentials']);
    }

Второй вариант, постараться запихать код метода в максимально маленькое количество строк, получив, такое нечитаемое нечто в 13 строк кода вместо 36.

    public function login(ServerRequestInterface $request): ResponseInterface
    {
        $params = $request->getParsedBody();

        return !$this->validator->isValid($params, [
            'username' => 'required|string',
            'password' => 'required|string',
        ]) ? $this->responseFactory->createJsonResponse(400, ['error' => 'Invalid request parameters']) : (
            ($auth = $this->authService->authenticate($params['username'] ?? '', $params['password'] ?? ''))->isSuccess() ? 
                $this->responseFactory->createJsonResponse(200, ['message' => 'Login successful', 'token' => $auth->getToken()]) : 
                $this->responseFactory->createJsonResponse(401, ['error' => 'Invalid credentials'])
        );
    }

Мы сократили код почти в 3 раза, но такой метод не пройдёт ни одно код ревью по очевидным причинам. Так же стоит уточнить, что 2 примера с разделением на методы и сокращением строк кода через тернарные операторы, полностью проходят по первому принципу солид и psr стандартам php. Да, код в моём примере меньше 50 строчек, но если бы мы добавили ещё несколько условий, например дополнительно проверку токена, то контекст бы не изменился.

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


public function login(ServerRequestInterface $request): ResponseInterface
{
    $params = $request->getParsedBody();

    // Validate request parameters
    if (!$isValidLoginParameters($params)) {
        return buildLoginResponse(400);
    }

    // Authenticate user (мы ж уже проверили, что всё валидно, зачем ещё раз на null проверять?)
    $authResult = $this->authService->authenticate($params['username'], $params['password']);

    if ($authResult->isSuccess()) {
        return buildLoginResponse(200, ['token' => $authResult->getToken()]);        
    } else {
        return buildLoginResponse(401);
    }
}

function isValidLoginParameters($params): boolean
{
    $isValidParameters = $this->validator->isValid($params, [
        'username' => 'required|string',
        'password' => 'required|string',
    ]);

    return $isValidParameters;
}

function buildLoginResponse($code, $resp_params): ResponseInterface
{
    switch ($code) {
    case 200:
        return $this->responseFactory->createJsonResponse(
            200,
            array_merge(['message' => 'Login successful'], $resp_params)
        );
    case 400:
        return $this->responseFactory->createJsonResponse(
            400,
            ['error' => 'Invalid request parameters']
        );
    case 401:
        return $this->responseFactory->createJsonResponse(
            401,
            ['error' => 'Invalid credentials']
        );
    }
}

P.S. Возможны ошибки синтаксиса, т.к. я в прошлый раз на PHP писал в 2009-м, но суть идеи, думаю, понятна.

Вот по этим аспектам и надо разделять, а не тупо каждую строку в отдельную функцию выделять.

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

А именно метод buildLoginRespons не совсем соответствует принципу SRP т.к. занимается отправкой и удачных и ошибочных ответов. Так же он имеет неочевидное поведение. Если мы передадим любой другой код, скажем 403, то метод ничего не сделает, либо вызовет ошибку 500 (звисит от ЯП), можно добавить default значение (или return в конце метода), но это всё-равно будет-нарушением исходной логики.

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

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

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

А именно метод buildLoginRespons не совсем соответствует принципу SRP т.к. занимается отправкой и удачных и ошибочных ответов. 

Занимается отправкой ответов - это одна обязанность. Для браузера абсолютно параллельно какой там статус, так что странно их разделять на успешные и нет. И вообще хорошо, когда она совсем абстрагирована на уровне фреймворка, и функция render импортирована в твой контроллер. Тогда бы не пришлось бойлерплейт вида $this->responseFactory->createJsonResponseпостоянно дублировать и генерация ответа спокойно в 1 строку умещалась, а не в 4.

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

И было бы что-то типа

public function login($params): ResponseInterface
{  
    // Authenticate user 
    $authResult = $this->authService->authenticate($params['username'], $params['password']);

    if ($authResult->isSuccess()) {
        return render('status' => 200, 'json' => ['token' => $authResult->getToken()]);
    } else {
        return render('status' => 401, 'json' => ['error' => 'Invalid credentials']);
    }
}

Другими словами, изначально длинная функция не является необходимостью. Она является следствием 2 вещей:
1) непродуманной организации фреймворка
2) недостаточной выразительности языка

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

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

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

Для браузера да, но не для фронтенда.

Тогда бы не пришлось бойлерплейт вида $this->responseFactory->createJsonResponseпостоянно дублировать и генерация ответа спокойно в 1 строку умещалась, а не в 4.

В вашем примере так же копируется строчка с render.

И возвращать не boolean, а осмысленный список ошибок валидации, который можно сразу на фронт передать. И в идеале, чтобы была возможность её вообще в отдельную миддлевару вынести

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

Очевидно же из контекста, что он опциональный.

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

С ним бесполезно разговаривать. Он думает, что программировать учатся по книгам, и если в книге написано «декомпозируй!» — то думать не нужно, нужно бежать декомпозировать.

Вы так эпично обосрались с чтением книги вашего любимого автора, что теперь следите за всеми моими комментариями? xD

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

вашего любимого автора

Мой любимый автор — Рэймонд Чандлер.

сколько вы тут не пыжьтесь

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

Ну, прижали тебя по фактам, имей мужество признать свою ошибку. Но нет, извивается как уж на сковородке, лишь бы не признавать очевидного 🤦‍♂️

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

О, мурло всё-таки вылезло, перешло на «ты». Я думал, потребуется больше времени, чтобы соскрести с быдла вычитанное из книжек, — но нет, природа сильнее.

Что ж ты сидишь страдаешь на таком плохом Хабре? Понятно, что на зарубежных форумах тебе прямым текстом не скажут, что ты токсичный дурачок с раздутым самомнением. Там толерантность такая, что нельзя ничего напрямую сказать.

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

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

Что ж ты сидишь страдаешь на таком плохом Хабре? 

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

Понятно, что на зарубежных форумах тебе прямым текстом не скажут […]

Сразу видно, что вы никогда не защищали свой PR против Валима или — хуже того — кого-нибудь из erlang core.

Там толерантность такая, что нельзя ничего напрямую сказать.

А вы-то откуда это знаете?

А тут стоит твою карму посмотреть и уже всё понятно […]

Да уж. Кроме того, бешусь тут не я, не правда ли?

xD

Вы никогда не замечали, что оскал после сказанной глупости — свидетельство невысокого ума?

подленькое поведение

А подленькое-то в чём? Ну дурак, ладно. Хабрахомяков не уважаю и на карму стойку не делаю — виновен. Код пишу не так, как написано во втором издании целой одной книги — признаю. А подлость-то тут где? Я и анонимность не храню, и в рыло при случае стукну, что ж тут подлого-то?

Смирись.

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

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

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

В вашем примере так же копируется строчка с render.

Да. Просто когда это же выражено более длинной записью `$this->responseFactory->createJsonResponse` это выглядит, как визуальный шум. В современном PHP есть возможность указать делегирование? Что мы, вызывая в контексте своего класса функцию createJsonResponse, автоматически делегируем обработку этого вызова в $this->responseFactory

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

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

У меня сейчас часть работы рефакторинг такого сложного алгоритма.

Да, некоторые части типа выбора строчки в матрице имеет смысл вынести из под-функций.

Но какая вам нафиг разница, каким методом матрица нормализирована, к примеру? Вам вполне достаточно названия вида build_tf_id_normаlized и все.

К тому же если вы оставили вменяемые коментарии - современные ИДЕ их подсвечивают над функцией по ховер.

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

Верить комментариям, когда функция уже требует рефакторинга — самая пагубная привычка из возможных. Ну и да, vim умел показывать комментарии к функциям лет примерно 40 назад, а современные IDE полагаются на Language Server’s, в которых для разных языков могут быть разные договоренности, так что весь пассаж про современные IDE лишен смысла.

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

А портянка сродни обфусцированному коду)

Так небольшие функции и тестировать проще. Зачем держать ее реализацию в голове, если она рабочая. Главное знать зачем она, а для этого и назвать можно по функциональности. И вообще, в одной большой функции порой переменным уже адекватное название не подберёшь, и появляются различные temp t1 t2.

Я конечно понимаю, что суть не в этом, но автор, вы пересматривали Хоббита, статью назвали "Туда и обратно", а на картинках у вас путь через Морию и Лориен к Ородруину, вместо Туманных гор, Лихолесья и Одинокой горы.

Вот использование слова "подсветил" меня одного бесит? 😁
Зачем их столько в тексте?
И сюда же слово "рефлексия" и производные от него ...

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

Интересная статья - спасибо.

На пути от джуна к мидлу мне было бы полезно знать, что вопросы — это на самом деле ответы. Да-да :)

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

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

Может я еще не дорос, но мой первый ответ это "А для чего вам нужны эти дашборды?".

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

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

Спасибо за хорошую статью - не часто увидишь такое вкрадчивое и обдуманное чтиво на эту тему. Думаю со временем моего роста я смогу с нее еще что-нибудь почерпнуть.

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

P.S. очень незаурядно вы прорекламировали свой тг. После прочтения вернулся к нему, чтобы узнать побольше, а оказалось своего канала нет в профиле .-. . Выходит и не реклама.

P.P.S. Даже жаль стало что отклонил недавно предложение пообщаться с hr из вашей компании в пользу другой :c ...

А зачем Бильбо в Мордор понесло?

Это совсем другая история ..

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

Если это произойдет ночью, кому девопсы должны об этом сообщить?

Никому. Поддержка сообщит. Возможно там должны бытьтдежурства. Девопсы пусть спят.

Отличный текст и очень ценный пример! Но как же хочется узнать, что происходит с сотрудниками Middle+ уровня в вашей компании? Какой рост у них "туда и обратно"? Особо на фоне массовых сокращений B2C отдела. Люди проработавши 6+ лет вынуждены искать себе место в компании, и отбивать двери других команд без гарантий, что вакансии вообще есть. Насколько бесчеловечно может поступать эта корпорация со своими сотрудниками. Прошу вас, не верьте людям из касперского. Вы в любой момент можете быть выставлены за дверь, потому что так, решил какой та менеджер, имейте это ввиду. Каким бы ценным специалистом вы бы не были! Ой прошу прощения... Не сокращения, а оптимизация... Каков путь оптимизации "туда и обратно"? А, Дмитрий?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий