меня тут триггернуло в текущей мега-дискуссии на слова https://mokum.place/alf/693637#c2099449 "Что до длины стектрейса, я всегда предпочту 1000 функций, каждая "so short that its correctness is painfully obvious" (ц) 10 функциям на пятнадцать экранов каждая."
я для себя разделяю "кодовую" сложность кода и "структурную" сложность кода. "Кодовая" — это, что находится внутри, условно, одной функции — например, если нам надо рассчитать какую-нибудь свертку многомерной матрицы, то этот код будет занимать сколько-то там строк, причем разбивать этот код на дальнейшие функции скорее всего будет контрпродуктивно. ‎- псы в рапиде
"Структурная" сложность кода — это вся организация, то есть разбиение на функции, классы, модули и проч. Структурная сложность, очевидно, может и помогать и мешать. Кодовая сложность обычно неустранима. Условно говоря, почти любую систему можно написать в виде одной простыни размером в сотни тысяч строк, и если из этой простыни ничего нельзя удалить — значит, примерно такова "имманентная сложность задачи". Структурная сложность может только увеличивать кол-во строк (но конечно, облегчать понимание системы). ‎- псы в рапиде
(здесь речь не про то, что функция map + reduce способна уменьшить размер того файла, что мы пишем — в этих вычислениях размер системных библиотек тупо суммируется к юзерскому коду). ‎- псы в рапиде
Почему я с подозрением отношусь к идее экстрагировать все в функции (до определенного момента)? Потому что каждая функция для меня — это контракт. Контракт что-то дает тебе, но и что-то требует. У меня есть одна иллюстрация этого тезиса [«Никита Сергеевич! Мы видим, что свадьба дочери товарища Полянского была для Вас мощным средством познания окружающей действительности».]: https://github.com/thoughtbot/paperclip/blob/master/lib/paper... ‎- псы в рапиде
^ буквально все, что делает этот модуль на 89 строк — это сравнение двух строк и бросание исключения, если они не совпадают. Однажды я потратил час, пытаясь сделать так, чтобы paperclip перестал это делать, а просто использовал то, что реально внутри, не обращая внимание на расширение. У меня это сделать не получилось, поэтому сейчас перед вызовом paperclip делается мега-залепуха на восемь строк, которая вытирает жопу этому несчастному модулечку. ‎- псы в рапиде
Так вот. Посмотрите на текст этого модуля и скажите сами себе — какой контракт у функции mapping_override_mismatch? ? mapped_content_type? да в общем любой тамошней функции. я не хочу заключать все эти контракты, я не понимаю, что они мне дают. ‎- псы в рапиде
ЧСХ, написание кода в бесструктурном стиле не означает, что там нет невидимых функций. Любимые Зверьком 140-строчные функции в коде мокума состоят из весьма четких шагов, каждый из которых мог бы быть извлечен в реальную функцию, которая вызывается в одном месте. Вообще, любой "линейный" код (игнорируя цикломатическую сложность), очевидно, "структурирован" внутри себя. Мне кажется ценным и полезным понимать эту историю про "невидимые функции". ‎- псы в рапиде
Простейший способ доказать их существование — вспомнить о static single assignment и continuation-passing style. Там после каждой строки концептуально вызывается невидимая функция-"остаток". Естественно, для оптимизации никаких вызовов не происходит, но концептуально все именно так. Лексические переменные — это аргументы этих функций. Соответственно, у этих невидимых функций тоже возникают контракты (в нормальном случае они совершенно эфемерны) — проблемы возникают только тогда, когда контракт усложняется ‎- псы в рапиде
Тут становится понятнее, что можно decouple эти "невидимые функции" и идею цикломатической сложности. Вообще говоря, у нас может быть формально цикломатически-сложный код, который занимает скажем экран, но при этом его контракт как функции тривиален — например, у него на входе один аргумент а на выходе одно значение. при этом этот код может использовать другие переменные, находящиеся выше него, но это "вспомогательные" аргументы — и как раз попытка вынести этот код в явную функцию (и необходимость передавать эти вспомогательные аргументы) — может резко усложнить контракт этой функции (относительно ее контракта как просто фрагмента кода). ‎- псы в рапиде
<<placeholder для еще какого-нибудь абзаца который я наверное забыл>> ‎- псы в рапиде
Мне кажется, что авторы пейперклиповского модуля подразумевали совсем иной контракт: выраженный в методе #spoofed?; это как бы функция в теле класса. И если тебе не нравится как работает этот класс, подразумевается, что ты его заменишь целиком. ‎- mark
я не могу не отметить, что ровно об этом говорил Линус наш Торвальдс в контексте его знаменитой дискуссии с Танненбаумом относительно сравнительных достоинств монолитного и микроядра ‎- лицо не владеющее языком