По идее электросистемы и так от аккумулятора питаются. А пока машина едет, в любом случае крутится вал генератора. Без электричества в общем не останется.
Короткие имена - тоже не встречал. А вот например "вместо списка передавать в метод массив и 2 индекса в нём" и "использовать один раз выделенные массивы вместо создания List-ов" - такое очень даже было. Unity/C# если что.
Написать тормозно можно на чём угодно. Написать не-тормозно - почти на чём угодно. Вероятно авторы клона таки уделили больше времени оптимизациям, там где это нужно.
Ну дак и я о чём - потребуется новая сущность, которая будет заниматься сохранением, не делать лишнего итп. Т.е. утверждение: чтобы быстрый код превратить в архитектурно красивый, не потеряв в скорости - потребуется нечто больше, чем распилить его на паттерны.
Ну и не всегда это вообще возможно - скажем, если у нас тянется сохранение с сервера, всё равно будет некоторая общая сущность, которая выполняет запрос к серверу и вытаскивает оттуда это сохранение (а потом уже отдельные модули будут его части парсить, как им нужно). Распиливание же сохранения по отдельным модулям - уронит производительность.
Годный поинт кстати - если надо поразбираться в чужом коде без внятной IDE (а много ли их под C++ внятных-то) - то искать только полнотекстовым поиском. А тогда длинные названия очень и очень помогут.
Well, yes, и такое тоже бывает. Сталкивался и в C# и в C++. Понятно, что должно несколько факторов сложиться (компилятор не смог заинлайнить функцию, накладных расходов на параметры много итп), но бывает. Даже при условии, что функции не виртуальные (с виртуальными ещё lookup в vtable добавляется).
Но я тут больше о более сложных случаях, когда одна функция распиливается на несколько + заводятся дополнительно классы для инкапсуляции чего-нибудь (а тут уже и выделение памяти добавляется дополнительно и GC может сагриться в ненужный момент).
В самом проде рефакторить конечно не нужно. А вот "для прода" - почему нет-то? Если у нас есть новая фича, которая не вписывается в текущую архитектуру - мы можем либо собрать её "на костылях" либо порефакторить так, чтобы она в архитектуру вписалась. И второй вариант очень часто предпочтительнее (потому что в итоге будет меньше регрессионных багов из-за этих костылей).
Понятно, что если у нас фича экспериментальная (мы не знаем, зайдёт она юзерам или нет, может придётся отпилить её после АБ-тестов) или у нас жёсткий прессинг по времени (MVP для инвесторов нужен, скажем) - то тут только костыли. Но не всегда же так.
Да даже без этого - сколько примеров в играх, когда ради производительности пишутся ужасные спагетти (а не-спагетти тормозят как не в себя). Справедливости ради, я такие куски обкладываю длинными комментами с ответами на вопросы "почему так быстрее", "зачем так сделано" и "что будет, если это переписать".
Готов предположить, что после разделения ответственности по разным классам, какое-нибудь сохранение глобальных настроек (или там, прогресса пользователя в игре) будет дёргаться из нескольких разных мест и чаще, чем если всё в одном God Object держать. Не 5 мегабайт вместо 100 байт, но словить какого-то сорта ухудшение характеристик можно. Ну либо придётся дополнительно меры предпринимать, чтобы этого не допустить (а это уже усложнение кода конечно).
Вообще в написании админок (когда из требований - много заковыристой бизнес-логики, зато можно подзабить на расходуемые ресурсы и не сильно заморачиваться на предмет "лишний раз сделать запрос на сервер / перезагрузить страницу") - очень хорошо работает PHP с server-side rendering. Вот буквально, берём какой-нибудь Yii и на нём очень быстро можно штамповать CRUDы (даже генератор встроенный завезли), а при надобности всегда можно натаскать каких-то виджетов, чтобы логику на клиенте ваять, если нужна. Да, jQuery, да, по фронтенд-меркам технологии прошлого века. Но работает же. И делается быстро.
Дак система наследования, всё верно. Но если у нас попросили сделать котика, зачем сразу же делать пяток интерфейсов и иерархию на 3-4 уровня? Может быть лучше просто сделать котика? Конечно, потом могут попросить пёсика, змейку и ещё кого. А могут и не попросить, мы ж не Ванга, чтобы это предвидеть.
На практике человекочасы на рефакторинг и приведение в чувство выделяются совершенно спокойно при оценке задачи. Условно "чтобы впилить пёсиков и змеек, надо завести систему животных и вот это всё".
И да, бывают ситуации, когда "накостылять по-быстрому" это более правильно, чем ваять архитектуру. Например, когда мы пилим фичу, которая непонятно как повлияет на метрики продукта (и есть неиллюзорный шанс, что она после АБ-тестирования будет отпилена и забыта к чертям).
Нет, не трогают просто потому, что котика оказалось достаточно (в смысле, что не пришлось эту часть кода расширять).
А эт уже задача тимлида (или кто у вас есть) - управлять техническим долгом и выделять на это ресурсы. Причём совершенно из бизнес-соображений: "если не порефакторим счас, потратим на N% времени больше на изменение и на M% увеличим вероятность наплодить багов".
В теории, классы и интерфейсы надо проектировать так, чтобы неправильное использование приводило к ошибкам компиляции. Рефакторить тоже (соответственно после изменения иерархии классов все места с некорректным использованием не скомпилируются). Понятно, что не всегда так можно, но по крайней мере стремиться к такому никто не мешает.
Я тут топлю за то, что можно сначала написать простой код, а потом, когда именно этот код потребует усложенения (котенок мяукает только по средам, пёсик гавкает чётное число раз итп) - рефакторить и усложнять. А не наоборот. Ибо много раз уже сталкивался с тем, что наворочена красивая расширяемая архитектура, потрачена куча времени на её отладку, понаписано несколько тысяч строк кода. А потом у всех интерфейсов по одной реализации и вообще эту часть системы ближайшие три года никто не трогает.
Для MySQL и его друзей есть Percona Toolkit, при помощи которого можно такой финт ушами (без даунтайма чтоб) проворачивать (в комменте выше отписывал). Не серебряная пуля, но может быть полезно.
В случае с опциональными полями - да, тут абсолютно согласен.
Я тут наверное больше прикопался к тезису "дропнуть-добавить таблицу / поле в нормализованной БД несложно". Если нам надо добавить обязательное поле (например, мы теперь в таблице с событиями входа юзеров хотим всегда запоминать, с какого IP юзер зашёл) - нормализация не то чтобы поможет. Ну либо у нас будет хренова гора таблиц вида user_id, yet_another_field с зависимостями 1-к-1 на юзера и сборка всех данных по юзеру из этих таблиц превратится в многоуровневый join. Хотя согласен, alter-ить таблицу юзеров в таком варианте не надо. Но выглядит как костыль, если честно.
По идее электросистемы и так от аккумулятора питаются. А пока машина едет, в любом случае крутится вал генератора. Без электричества в общем не останется.
Буксировка бывает не только на мягкой сцепке. И строго формально да, буксируемый автомобиль эксплуатируется.
Короткие имена - тоже не встречал.
А вот например "вместо списка передавать в метод массив и 2 индекса в нём" и "использовать один раз выделенные массивы вместо создания List-ов" - такое очень даже было.
Unity/C# если что.
Написать тормозно можно на чём угодно.
Написать не-тормозно - почти на чём угодно.
Вероятно авторы клона таки уделили больше времени оптимизациям, там где это нужно.
Ну дак и я о чём - потребуется новая сущность, которая будет заниматься сохранением, не делать лишнего итп.
Т.е. утверждение: чтобы быстрый код превратить в архитектурно красивый, не потеряв в скорости - потребуется нечто больше, чем распилить его на паттерны.
Ну и не всегда это вообще возможно - скажем, если у нас тянется сохранение с сервера, всё равно будет некоторая общая сущность, которая выполняет запрос к серверу и вытаскивает оттуда это сохранение (а потом уже отдельные модули будут его части парсить, как им нужно). Распиливание же сохранения по отдельным модулям - уронит производительность.
Попробую дать VSCode ещё один шанс, пару-тройку лет назад пробовал, но он ломался на конструкциях вида "унаследоваться от реализации шаблона".
CLion - увы, платное.
Visual Studio как по мне - отлично, пока не начинаешь под Linux писать (а вот тут оно ломалось на Linux-овых хедерах, может конечно поправили уже).
QtCreator ВНЕЗАПНО весьма неплох (даже без Qt).
Годный поинт кстати - если надо поразбираться в чужом коде без внятной IDE (а много ли их под C++ внятных-то) - то искать только полнотекстовым поиском. А тогда длинные названия очень и очень помогут.
Well, yes, и такое тоже бывает. Сталкивался и в C# и в C++. Понятно, что должно несколько факторов сложиться (компилятор не смог заинлайнить функцию, накладных расходов на параметры много итп), но бывает.
Даже при условии, что функции не виртуальные (с виртуальными ещё lookup в vtable добавляется).
Но я тут больше о более сложных случаях, когда одна функция распиливается на несколько + заводятся дополнительно классы для инкапсуляции чего-нибудь (а тут уже и выделение памяти добавляется дополнительно и GC может сагриться в ненужный момент).
В самом проде рефакторить конечно не нужно.
А вот "для прода" - почему нет-то? Если у нас есть новая фича, которая не вписывается в текущую архитектуру - мы можем либо собрать её "на костылях" либо порефакторить так, чтобы она в архитектуру вписалась. И второй вариант очень часто предпочтительнее (потому что в итоге будет меньше регрессионных багов из-за этих костылей).
Понятно, что если у нас фича экспериментальная (мы не знаем, зайдёт она юзерам или нет, может придётся отпилить её после АБ-тестов) или у нас жёсткий прессинг по времени (MVP для инвесторов нужен, скажем) - то тут только костыли. Но не всегда же так.
Да даже без этого - сколько примеров в играх, когда ради производительности пишутся ужасные спагетти (а не-спагетти тормозят как не в себя).
Справедливости ради, я такие куски обкладываю длинными комментами с ответами на вопросы "почему так быстрее", "зачем так сделано" и "что будет, если это переписать".
Готов предположить, что после разделения ответственности по разным классам, какое-нибудь сохранение глобальных настроек (или там, прогресса пользователя в игре) будет дёргаться из нескольких разных мест и чаще, чем если всё в одном God Object держать.
Не 5 мегабайт вместо 100 байт, но словить какого-то сорта ухудшение характеристик можно. Ну либо придётся дополнительно меры предпринимать, чтобы этого не допустить (а это уже усложнение кода конечно).
H7H2V
Ого, не знал. А чем мотивировано? Или просто "исторически так"
Вообще в написании админок (когда из требований - много заковыристой бизнес-логики, зато можно подзабить на расходуемые ресурсы и не сильно заморачиваться на предмет "лишний раз сделать запрос на сервер / перезагрузить страницу") - очень хорошо работает PHP с server-side rendering.
Вот буквально, берём какой-нибудь Yii и на нём очень быстро можно штамповать CRUDы (даже генератор встроенный завезли), а при надобности всегда можно натаскать каких-то виджетов, чтобы логику на клиенте ваять, если нужна. Да, jQuery, да, по фронтенд-меркам технологии прошлого века. Но работает же. И делается быстро.
Дак система наследования, всё верно. Но если у нас попросили сделать котика, зачем сразу же делать пяток интерфейсов и иерархию на 3-4 уровня? Может быть лучше просто сделать котика? Конечно, потом могут попросить пёсика, змейку и ещё кого. А могут и не попросить, мы ж не Ванга, чтобы это предвидеть.
На практике человекочасы на рефакторинг и приведение в чувство выделяются совершенно спокойно при оценке задачи. Условно "чтобы впилить пёсиков и змеек, надо завести систему животных и вот это всё".
И да, бывают ситуации, когда "накостылять по-быстрому" это более правильно, чем ваять архитектуру. Например, когда мы пилим фичу, которая непонятно как повлияет на метрики продукта (и есть неиллюзорный шанс, что она после АБ-тестирования будет отпилена и забыта к чертям).
Нет, не трогают просто потому, что котика оказалось достаточно (в смысле, что не пришлось эту часть кода расширять).
А эт уже задача тимлида (или кто у вас есть) - управлять техническим долгом и выделять на это ресурсы. Причём совершенно из бизнес-соображений: "если не порефакторим счас, потратим на N% времени больше на изменение и на M% увеличим вероятность наплодить багов".
В теории, классы и интерфейсы надо проектировать так, чтобы неправильное использование приводило к ошибкам компиляции.
Рефакторить тоже (соответственно после изменения иерархии классов все места с некорректным использованием не скомпилируются).
Понятно, что не всегда так можно, но по крайней мере стремиться к такому никто не мешает.
Я тут топлю за то, что можно сначала написать простой код, а потом, когда именно этот код потребует усложенения (котенок мяукает только по средам, пёсик гавкает чётное число раз итп) - рефакторить и усложнять. А не наоборот.
Ибо много раз уже сталкивался с тем, что наворочена красивая расширяемая архитектура, потрачена куча времени на её отладку, понаписано несколько тысяч строк кода. А потом у всех интерфейсов по одной реализации и вообще эту часть системы ближайшие три года никто не трогает.
Дропнуть-добавить разве не о том? Если таблицы дропать и добавлять, тогда конечно согласен, с этим проблем нет.
Для MySQL и его друзей есть Percona Toolkit, при помощи которого можно такой финт ушами (без даунтайма чтоб) проворачивать (в комменте выше отписывал). Не серебряная пуля, но может быть полезно.
В случае с опциональными полями - да, тут абсолютно согласен.
Я тут наверное больше прикопался к тезису "дропнуть-добавить таблицу / поле в нормализованной БД несложно". Если нам надо добавить обязательное поле (например, мы теперь в таблице с событиями входа юзеров хотим всегда запоминать, с какого IP юзер зашёл) - нормализация не то чтобы поможет. Ну либо у нас будет хренова гора таблиц вида user_id, yet_another_field с зависимостями 1-к-1 на юзера и сборка всех данных по юзеру из этих таблиц превратится в многоуровневый join.
Хотя согласен, alter-ить таблицу юзеров в таком варианте не надо. Но выглядит как костыль, если честно.