Заметки о костылях
Все же есть в этом мире порой некоторые вещи, которые можно обсуждать бесконечно.
И что самое замечательное, каждый раз такое обсуждение может закончиться совершенно непредсказуемым результатом, как для автора, так и для читателей.
Любому разработчику известно для чего нужды костыли, велосипеды и грабли. И наверняка у каждого уже есть парочка в гараже, а так же бубен на стенке для особых случаев. Если у вас еще их пока нет, вы либо совсем недавно присоединились к нам (Возможно, только вчера открыли «PHP для чайников» и через пару дней у вас они тоже будут. Костыли будут конечно же свои, не многие из нас открывают свои чуланы чужим.) или ставите задачи для вашей армии раз***в (пусть тут будет слово близкое вам сегодня), когда очередное недоразумение уронит вам сервер, выведет кривой отчет или просто откажется запускаться программа. Оставлю тихую надежду, что остальные, те кто пользуется плодами этого совместного творчества сюда не зайдут.
Начнем с определения.
«Костыль — приспособление для поддержания веса тела пациента при стоянии и ходьбе» (с) Вики
То есть «костыль» не такое уж и плохое решение, как может показаться. Думаю, не один здравомыслящий человек не будет отказывать от возможности ходить, когда этого лишён, но он точно не захочет опираться на клюку когда все в порядке.
Определение есть, теперь немного о предмете (пациенте)
Считается что приложение (решение, система…) пишется с первого раза, без ошибок и не требует не только поддержки, но и развития. О процессе утилизации — переходе от одного решения к другому (вы надеюсь не верите в зубных фей и в вечно работающие сервера, базы данных, платформы, технологии) промолчим, как и об оценке каждого их этих этапов.
Вообще все ещё немного страшнее, существует целые направления в науке занимающие оценкой проектов, анализу рисков и остальной околоразработческой деятельности.
Назовем эту простую стратегию – «Стратегия святого Грааля разработки». Никто никогда не видел быстро-качественно-дешево, но все уже хотят еще вчера, и что самое интересное все знают, что это такое — «сделайте мне красиво».
Результат очевиден.
В итоге, в погоне за великой целью гибнут многие из нас, кто в странных технологиях: гибкая разработка, автоматизированное тестирование, парное программирование и т.д., и т.п.; кто в темных углах различных средств и языков, начиная от C++, Java, Pyton, PHP, JS; кто на подобных форумах ^_^
А давайте предположим, что пациент изначально больной (в надежде что не головой, бывают и такие варианты). Что, если единственно, что ему надо — не научиться бегать (конечно бегать, ведь ходить или ползать неинтересно, где вы встречали вменяемые сроки отведенные на разработку), а получить представление о беге, почувствовать ветер и скорость, пусть это будет просто вентилятор и человек бегающий с кустом в руках вокруг. И тогда все становиться гораздо проще.
Тогда достаточно используя различные костыли создать нечто способное ковылять и по мере развития, если конечно оно последует (реальный бизнес такая не предсказуемая вещь), мы потихоньку будет сначала убирать, то один, то другой, при условии полной или частичной «реабилитации» «пациента».
В итоге каждый получит что хотел: клиент получить возможность бегать и не надорвётся в попытках взять стометровку на олимпийских спринтах, да и разработчики не будут судорожно подбирать очередную клюку в надежде, что вот как раз теперь она нужного размера.
Резюмируя.
Исходя из нашего предположения, вы как разработчик всегда должны проектировать две системы (а иногда и больше, гораздо больше): первая это то, что можно сделать прямо сейчас, и «идеальная» — включающая идеальное представление о том, какой она должна быть (вдруг и правда, нужно будет выиграть олимпиаду).
Вы должны уметь в уме создавать решения способные изменять любую имеющуюся систему на набор костылей и наоборот.
И главное, в следующий раз, когда будет решать ну прямо очень сложную задачу, попробуйте для начала вот ту палку в углу, которую поставили пару дней назад, возможно, что и не заработает, но поковыляет.
Господа программисты! Изобретайте велосипеды!
Я морально готов к тому, что меня заминусуют, плюнут в лицо, наср*т за шиворот и забанят в гугле. И всё-же.
Господа программисты-сисадмины! Изобретайте велосипеды! Если позволяет время, лучше посидите и попытайтесь решить задачу своими силами. После любого результата (даже отрицательного) поищите готовые решения.
Почему нужно писать велосипед? Чтобы пришло бОльшее понимания задачи, для развития своих навыков и как спортивный интерес.
Пописав «велосипеды» в своё время (да и чего там говорить, до сих пор пишу) и увидев узкие места своего собственного кода, я не раз обращался к готовым решениям. Местами находил «грабли» посерьёзнее моих. В некоторых точно такие же затыки, как и у меня (что приводит к выводу о идентичности решения).
К тому же при постоянно развивающихся технологиях пересмотр старых алгоритмов может иметь место.
Костыли и велосипеды для начинающих программистов
Приветствуем всех начинающих программистов, специально для вас наша студия провела опрос штатных программистов и собрала общее мнение в единую статью.
Что нужно учитывать начинающему программисту.
Многие новички считают свой код идеальным, но они заблуждаются. Идеального кода не существует! Любой код имеет возможности совершенствоваться. Как сказал один из наших программистов:
一 «Сколько бы лет ты не занимался написанием кода, новый все равно будет лучше и лучше предыдущего».
У начинающих разработчиков, узнавших о новом фреймворке или изучавших новый язык программирования, часто возникает непреодолимое желание прямо здесь и сейчас переписать проект с нуля «теперь-то уже точно правильно». Поспешим расстроить — это плохая практика. Реальность такова, что за каждым проектом обычно стоят бюджеты и сроки. Остановка разработки на несколько месяцев при переписывании проекта обычно никому не нужна. Постепенное переделывание проекта по модулям — хорошо. Снос до основания и переделывание с нуля — плохо.
Еще один из немаловажных вопросов — стоит ли бояться костылей? Нет, но к ним нужно относиться настороженно. Это рабочий, но не универсальный код, который желательно отметить комментарием. Костыли могут теряться со временем и при расширении/увеличении программы костыль скорее всего сломается/придётся от него избавиться. Костыли это меньшее зло. Большее — сорвать сроки!
Любому программисту всегда следует читать мануалы.
Мануалы — любая литература/статьи/обзоры/видео по той теме которую делаешь. Причем начинать можно с азов: if, переменные, память и до чего-то объемного: паттерны, архитектуры кода и что-то обособленное VR, верстка, оптимизация. Если застрял 一 спрашивай у опытных товарищей или на форуме. Можно сначала поискать информацию в интернете, а можно сразу бежать за советом — это вопрос совести.
Чужой код — это ловушка. Если ты не знаешь как это работает — значит не знаешь и результат работы кода.
Плагин = чужой код, который ты не знаешь.
Будь всегда готов что ОНО обновится и отвалится. Поэтому плагины стоит использовать с осторожностью.
Костыли и велосипеды Автоматика
Семь бед — один ответ
Если вы проработали с Автоматик1111 хотя бы пару дней, вы уже наверняка сталкивались с тем, что он сыплет в консоль ошибками, перестает что-либо генерировать, а после обновления обязательно отваливается какое-нибудь расширение.
Причина у этого очень простая: плохой код. Даже вот так: ПЛОХОЙ КОД. Приведу пару примеров.
Давайте сначала разберемся, что же такое ХОРОШИЙ КОД. На мой взгляд определение хорошего кода очень простое: это код, который легко поддерживать и расширять. Всё остальное, все эти KISS, DRY, SOLID, MVP и паттерны проектирования, призваны лишь помочь в этом.
Поддерживать — значит исправлять ошибки, добавлять фичи, изменять внутреннюю логику, при этом ничего не ломая. Сюда же входит хорошо читаемый код, чтобы разобраться в нем cмог не только автор, но и все, кто придет после него.
Расширять — значит наращивать функционал, добавлять новые модули и не волноваться, что это испортит кому-то жизнь.
Вот имея это в виду давайте нырнем в исходники и посмотрим несколько примеров, причем даже не из самого Автоматика, а из раширения ControlNet, в котором я провел больше всего времени.
Hardcoded strings
Это любопытный "паттерн", который я регулярно встречаю в исходниках Автоматика. Если нужно передать какой-то параметр, почему бы не сделать его строкой?
Вот вам пример. В КонтролНете есть три типа масштабирования картинки.
Так вот, угадайте с трех раз, как этот параметр используется в исходниках?
Абсо-факин-лютели. resize_mode должен принимать одно из двух значений: "Scale to Fit (Inner Fit)" или "Envelope (Outer Fit)" с точностью до пробела и скобки. Не будем даже обращать внимание на оптимистичное предположение автора, что других типов скейла никогда не добавится, поэтому третий проверяется просто через Else.
В чем проблема такого подхода?
1. Эти строки должны идеально совпадать в нескольких местах кода. Более того, если вы делаете api, чтобы использовать КонтролНет из другой программы, вы должны передавать эти строки в точности в таком же виде. Если кто-нибудь решит поменять хотя бы одну букву в интерфейсе, это изменение повлечет за собой цепную реакцию, нужно будет менять эту строку в нескольких местах кода, а также во внешних программах.
2. Разработчики работают в IDE, средах программирования, которые ускоряют написание кода. Например в C# я могу создать enum ResizeType, и когда я начну набирать ResizeType, IDE мне сразу выдаст список доступных опций и я смогу выбрать одну из них. Мне не надо в точности запоминать, как пишется та или иная константа. В случае со строками из КонтролНета это, понятное дело, не сработает. И вам надо будет искать нужное место в исходнике, копировать строку и вставлять ее в ваш скрипт.
Казалось бы, это не самая важная фича, почему же я уделяю ей столько внимания? Потому что это показывает в целом подход авторов. Главное, чтобы работало сейчас, а потом уже другие люди будут бороться с последствиями.
Подсчёт параметров
Это забавное следствие того, что авторы не думают о дальнейшем расширении своего кода, а потом латают дыры на бегу.
Итак, в ControlNet добавилась фича, которая позволила использовать несколько Контролов подряд. Вам ведь тоже интересно узнать, как именно это получилось у автора?
Есть основная функция process, которая принимала 14 параметров (это все параметры, которые существуют на интерфейсе, включая злополучный скейл, модель и так далее).
Зажмурьтесь и представьте себе самый идиотский способ, как добавить еще один набор параметров сверху. Возможно вам повезло, и вы угадали. Если надо передать еще один КонтролНет, сделаем 28 вместо 14 параметров. Еще один? Легко! 42 параметра!
И прямо в коде в нескольких местах у автора был подсчет числа параметров с делением его на 14. Число 14 встречалось несколько раз.
Уже в следующем обновлении ему понадобилось добавить ещё один параметр. Смекаете? Автор был мудр, возможно даже вспомнил про SOLID и DRY, поэтому ОН ВЫНЕС ЧИСЛО ПАРАМЕТРОВ В КОНСТАНТУ!
Теперь я, как разработчик сторонних плагинов, должен при каждом обновлении лезть в исходник и смотреть, не изменилось ли число параметров. Потому что если я вдруг передам не 30, а 28 аргументов, то всё сломается.
Поймите меня правильно, я начинал карьеру с программирования на ассемблере. Такие вещи там в порядке вещей. Но я слышал, что некоторые называют Python объекто-ориентированным языком. Слышал даже, что в нем есть удобные словари и списки. Какие-то там тьюплы, тьфу, язык сломаешь.
Если вы думаете, что это волюнтаризм отдельно взятого автора расширения, то вы ошибаетесь. В самом Автоматике ровно так же сделана обработка подгружаемых скриптов. При инициализации каждого стороннего скрипта читается число аргументов и все они добавляются в один общий огромный список. И когда вы вызываете скрипт через api, в этой колбасе по числу аргументов и номеру скрипта находятся нужные. Я пишу и сам в это не верю. Но нет, перепроверил, всё правильно. Именно так это и реализовано.
Это лишь два простых примера плохого кода из многих. Такой код трудно поддерживать и сложно расширять. Говорить о том, что A1111 — это production-ready решение, мягко говоря, рановато. Я пишу плагины для внешних программ, которые обращаются к Автоматику, и каждый раз после обновления у меня что-то ломается из-за такой убогой архитектуры.
Возможно в какой-то момент я и сам сломаюсь, запрусь в комнате на месяц и просто сделаю собственный Автоматик.
Джуны бьются за респект
Открытый исходный код — это прекрасная концепция. Но когда его не контролируют, когда нет команды ревьюверов, получающих за свою работу деньги, это часто приводит к появлению монстров Франкенштейна, подобных Автоматику.
Любой второклассник может сделать клон репозитория, внести изменения и запушить их в продакшн. И с большой вероятностью их примут. Главное, чтобы работало прямо сейчас. А как потом это будет поддерживаться — дело десятое.
Я не думаю, что пулл-реквесты делают только второклассники, но давайте честно: кто с большей вероятностью будет тратить время на работу с Open Source, взрослый состоявшийся разработчик с семьей и работой или студент с горящими глазами и минимумом опыта за плечами?
И это, наверное, здорово. Благодаря такому подходу новые фичи появляются в Автоматике довольно быстро. Но при этом код разрастается, увеличивается технический долг, всё начинает зависеть от всего, и в конце концов с очередным обновлением вас встречает в консоли радостное сообщение, что приложение сломалось и больше работать никогда не будет.