Этот код иллюстрирует пример когда у вас был объект, вы его мутировали, а потом через вереницу ифов использовали:
auto image = getImage();
image.flip();
if (someLongCondition1)
foo();
if (someLongCondition2)
bar();
// your code goes here
baz(image); // упс, вам тут нужен был исходный имадж, а не флипнутый
Да, пример тривиальный (на то он и пример). В случае мувнутого объекта вам тулы скажут что вы делаете что-то не то, а в этом случае вам надо полагаться на ревью/тесты.
Или вам никогда не приходилось часами отлаживать баги где десяток стейтов накладываются друг на друга?
В случае move-only API «старый» объект будет содержать пустую картинку, а clang-tidy будет предупреждать, если вы захотите этим объектом воспользоваться кроме как попытавшись записать новый:
auto image = getImage();
auto mirrored = std::move(image).mirrored();
std::cout << image.size() << std::endl; // warning, bugprone-use-after-move
image = getAnotherImage(); // OK
Такой подход лучше тем что существует тулинг, который позволяет отслеживать неправильное использование «мувнутых» объектов, а для общего случая (например mirror/nonmirror) такого тулинга нет — только программист знает, что ему нужно.
Если вам нужна копия, то придется явно это написать, и ревьюверу будет видно что тут тяжелая копия:
auto image = getImage();
auto mirrored = Image(image).mirrored();
Или можно воспользоваться Copy-On-Write (если объект полностью иммутабельный, то вам даже deep copy не нужно делать on write, что упрощает код и устраняет большинство проблем COW) и применить ваше решение с флажком «orientation» — тогда и копирование дешевое и иммутабельность сохраняется.
ну смотрите, у вас есть копирование. Причем картинки, тяжеловесного объекта. Вы всерьез считаете, что это всегда хорошо?
Нет, не считаю, я считаю что не надо заниматься premature optimization и кидаться сразу делать АПИ мутабельным просто потому что «это быстрее».
Всегда можно воспользоваться вторым вариантом с перегрузкой по rvalue. Можно даже пойти дальше и оставить только эту перегрузку и не перегружать метод от lvalue, тогда уже компилятор будет бить по рукам, а не профайлер. На эту тему был доклад на cpp russia в прошлом году. Возможно, если бы писал класс Image, я бы так и сделал=)
Или, раз уж мы затронули тему игровых движков, то можно вспомнить статью Кармака 8 летней давности где он рассуждает о том что pure functions это хорошо, а сайд эффекты — плохо.
Это ложная дихотомия — либо мутабельность, либо скорость — можно взять и то и то, было бы желание.
Возможно, пример с картинкой не самый удачный, просто первое, что пришло в голову.
Вероятно, какой-нибудь class Matrix и transpose() vs. transposed() было бы лучшим примером.
Да, это так. Но тут скорее речь о том, что если есть выбор между тем, менять состояние объекта или не менять, то лучше избегать побочных эффектов, то есть не менять.
Например:
auto image = getImage();
image.mirror(); // плохой метод, меняет состояние объекта
auto mirrorImage = image.mirrored(); // хороший метод, состояние не модифицируется, но есть копирование
Тем более, что в современных С++ копирования можно избежать, если добавить перегрузку от rvalue-ref (метод Image mirrored() &&), например:
auto mirrorImage = getImage().mirrored(); // отлично, копирования нет, внешних побочных эффектов нет
В других языках может быть не всегда возможно избежать копии, но выбирая между производительностью и безопасностью\удобством чтения, лучше выбирать второе — оптимизировать ботллнек всегда можно потом. Например, иммутабельные строки выглядят как хороший пример такого выбора.
Я пролистал ссылку, понял что ничего не понимаю в Джаваскрипте и закрыл — я сходу не увидел высокоуровнего описания, а вникать в портянки кода на ЖС у меня нет желания, извините, веб разработка — не моё.
Нет, я прекрасно знаю, что все эти проблемы решаемы в мультирепе, скажем, в 2 Гисе был свой набор скриптов для этого. Можно и деб-пакеты собирать из различных репозиториев и рулить зависимостями на этом уровне, тоже подход. По всякому можно, я и не утверждаю что монорепа лучше чем мультирепа, я утверждаю что безапелляционно заявлять что «Х — говно» это профанационный уровень, которым проникнута вся статья.
Тулинг там довольно тривиальный
Именно так и работает селективный чекаут в ya make=)
Да, гитхаб это клево и удобно, а как быть с переменованием функций, например? В Аркадии я могу взять и заменить Stroka на TString одним коммитом.
А вот взять товарищей из Qt, у них мультирепа. Вот я хочу переименовать функцию из QtCore которая используется в другом сабмодуле. Это надо добавить функцию-обертку, закоммитить, пойти в другой модуль, заюзать враппер там, закоммитить, пойти в QtCore и наконец переименовать функцию, избавившись от обертки, закоммитить. Не слишком ли много действий для такой простой задачи?
Смысл в монорепе в том что у вас есть легкий доступ к тем самым велосипедам. И да, «не связанные» проекты в том числе хотят иметь этот доступ. Нужна библиотечка из Утилей — подключили одной строкой в ya.make. Захотела ваша тулза из 10 строк ходить в YT — фигня вопрос, ну подумаешь вместо 10 секунд компилируется теперь 40 минут. Зато экономится время разработчика — не надо пилить свой локальный велосипед когда есть алгортим/функция/библиотека/велосипед в Аркадии. Например, поиск Маркета юзает плюс-минус тот же код, что и основной поиск.
Не, я не спорю, что при должном тулинге можно сделать это и на мультирепах, но проблема в том что и в случае монорепы и в случае мультирепы этот тулинг нужен (ни то ни другое не является серебрянной пулей и не работает из коробки) — в силу тех или иных причин Яндекс выбрал монорепу и связанный с ней тулинг. Утверждать, что монорепа — говно, «забыв» о необходимости (другого) тулинга для мультирепы — это писать фигню, потому что складывается впечатление что в Яндексе дурачки, а вот мультирепа все проблемы решит из коробки.
И в любом тексте можно найти какой-нибудь изъян, что не делает этот текст ложным.
Ну так там не один такой изъян — про монорепу фигня написана, про качество кода, про велосипеды, про легаси. То есть оно конечно в какой-то мере есть (покажите мне проект без легаси), но не это ужас-ужас достойный целой статьи.
С чем я могу согласиться — это переработки, но это как-то о-малое от всего описанного.
Да даже бывшие/нынешние сотрудники Маркета (вроде меня) не в курсе происходящих ужасов, что уж о там о руководстве говорить=)
Мой изначальный поинт в том что не надо принимать на веру всё что пишут в интернетах и автор может быть (скажем мягко) не совсем объективен.
Да, во всякую дичь легче поверить — я когда читал всё это поймал себя на мысли «ну нихрена себе там у джавистов», но, поразмыслив, всё же решил, что слова автора надо делить примерно на 10. Например его поинт про то что на маке/венде не собирается разбивается о то, что это и не нужно делать ибо неудобно — яндексовая система сборки позволяет собирать удаленно на (линуксовых) серверах. Зачем собирать 2 часа утилиту если можно собрать ее за 10 минут на сервере? Опять же, когда я устраивался я всё это выяснил заранее и не стал брать Мак (вероятно, зря).
Если бы я до сих пор работал в Маркете и был в курсе что там в команде джавистов я бы мог подтвердить или опровергнуть описанное в статье. Из того, что я видел и где я работал — ничего подобного и близко не было.
Прежде всего самому Яндексу. Чем больше нашумит статья, тем больше вероятность, что высшее руководство с ней ознакомится и предпримет какие-либо меры.
Я работал в каком-то другом маркете и ничего подобного описанному в статье у нас не было. Либо всё за 2 года ТАК испортилось, либо автор слегка (совсем чуть-чуть) преувеличивает проблемы.
Представим теоретическую ситуацию что в статье — ложь. Что должно делать руководство в этом случае? Ну проведут они расследование, выяснят, что переработок нет или почти нет, статический анализ есть и на венде люди прекрасно работают, а человек просто обиделся на что-то, вот и пишет всякое. А потом другой человек прочитал это и не пошел работать в Яндекс, основываясь на недостоверных/неполных данных. Кто в этой теоретической ситуации выиграл?
В Яндексе, собственно, политика такая вместо того, чтобы строить внутренние процессы так, чтобы не было стыдно, если вдруг что-то станет достоянием общественности, — там бьют по башке всех, кто хотя бы минимально проявит свою нелояльность.
А еще можно написать в рассылку команды и вам (внезапно!) ответят в течении пары часов где предложат способ лучше и правильней чем всё что ты сумел нагрепать в сорцах (которые тоже устаревают!). По крайней мере, такой подход для YT (яндексовый велосипед для мап-редьюс) работал отлично.
Те, кому нравилось работать в Яндекс.Маркете, не пишут такие статьи=)
Кто плюсует мне тоже интересно. Это достаточно забавно и интересно читать, но всё же ценность таких статей околонулевая (ИМХО) по сравнению с техническими статьями.
Ну вот прочитает человек такую статью, решит что Яндекс говно и не пойдет туда. Кому от этого лучше? Человеку, который не получит полезный опыт создания scalable систем? Яндексу, который не получит (возможно) ценного сотрудника?
вкратце — да, у вас есть список папок, которые содержат изменившиеся файлы, каждая папка — нода в графе, соответствующая листовому артефакту (бинарю или библиотеке). Надо «просто» пересобрать все зависящие компоненты.
А что, ya make для джавы не умеет собирать на удаленных хостах? Пару раз я собирал крупные компоненты локально (у меня был нубук линуксом, я как раз заранее выяснил, что на маке хрен что соберешь), сборка занимала несколько часов — очень быстро перестал это делать.
Но как можно понять, компилироваться такое будет очень долго.
Мне кажется, это в первую очередь не очень читаемо, тормознутость — отдельная проблема.
Основная и главная проблема noexcept в том, что нет compile-time проверки действительно ли оно noexcept.
Правда ваша, компилятор мог бы форсить noexcept как это делается для const.
Тем не менее, в clang-tidy имеется проверка bugprone-exception-escape, которая, судя по документации, как раз призвана ловить случаи, когда кидается исключение там где его не должно быть. Если у кого есть опыт использования этой проверки — поделитесь, пожалуйста.
Я дико рекомендую вот этот цикл статей на Хабре, развеивает кучу мифов и даёт представление о том куда и на что смотреть, если поймали data race habr.com/ru/post/195770.
Вы же сейчас о ключевом слове volatile, который вешают на переменную, а не о штуках типа asm volatile("" ::: «memory»);?
Если да, то у меня для вас плохие новости — либо у вас где-то есть барьер, который маскирует проблему, либо вы просто ещё не нашли багу.
Ключевое слово volatile не спасает от проблем многопоточности на relaxed-ordered архитектурах, потому что инструкции может переставлять процессор, а не компилятор (точнее, это могут делать оба, но volatile запрещает только второму).
Другое дело, что стандарт «нормального языка» ничего не говорит о многопоточности и memory ordering (поправьте, если ошибаюсь), а значит оставляет вас и компилятор в серой зоне — компилятор может вам помочь и напихать барьеров памяти, видя volatile, а может и не помогать и тогда ваш код будет содержать трудноотлаживаемую багу.
Этот код иллюстрирует пример когда у вас был объект, вы его мутировали, а потом через вереницу ифов использовали:
Да, пример тривиальный (на то он и пример). В случае мувнутого объекта вам тулы скажут что вы делаете что-то не то, а в этом случае вам надо полагаться на ревью/тесты.
Или вам никогда не приходилось часами отлаживать баги где десяток стейтов накладываются друг на друга?
Такой подход лучше тем что существует тулинг, который позволяет отслеживать неправильное использование «мувнутых» объектов, а для общего случая (например mirror/nonmirror) такого тулинга нет — только программист знает, что ему нужно.
Если вам нужна копия, то придется явно это написать, и ревьюверу будет видно что тут тяжелая копия:
Или можно воспользоваться Copy-On-Write (если объект полностью иммутабельный, то вам даже deep copy не нужно делать on write, что упрощает код и устраняет большинство проблем COW) и применить ваше решение с флажком «orientation» — тогда и копирование дешевое и иммутабельность сохраняется.
Нет, не считаю, я считаю что не надо заниматься premature optimization и кидаться сразу делать АПИ мутабельным просто потому что «это быстрее».
Всегда можно воспользоваться вторым вариантом с перегрузкой по rvalue. Можно даже пойти дальше и оставить только эту перегрузку и не перегружать метод от lvalue, тогда уже компилятор будет бить по рукам, а не профайлер. На эту тему был доклад на cpp russia в прошлом году. Возможно, если бы писал класс Image, я бы так и сделал=)
Или, раз уж мы затронули тему игровых движков, то можно вспомнить статью Кармака 8 летней давности где он рассуждает о том что pure functions это хорошо, а сайд эффекты — плохо.
Это ложная дихотомия — либо мутабельность, либо скорость — можно взять и то и то, было бы желание.
Возможно, пример с картинкой не самый удачный, просто первое, что пришло в голову.
Вероятно, какой-нибудь class Matrix и transpose() vs. transposed() было бы лучшим примером.
Например:
Тем более, что в современных С++ копирования можно избежать, если добавить перегрузку от rvalue-ref (метод Image mirrored() &&), например:
В других языках может быть не всегда возможно избежать копии, но выбирая между производительностью и безопасностью\удобством чтения, лучше выбирать второе — оптимизировать ботллнек всегда можно потом. Например, иммутабельные строки выглядят как хороший пример такого выбора.
Нет, я прекрасно знаю, что все эти проблемы решаемы в мультирепе, скажем, в 2 Гисе был свой набор скриптов для этого. Можно и деб-пакеты собирать из различных репозиториев и рулить зависимостями на этом уровне, тоже подход. По всякому можно, я и не утверждаю что монорепа лучше чем мультирепа, я утверждаю что безапелляционно заявлять что «Х — говно» это профанационный уровень, которым проникнута вся статья.
Именно так и работает селективный чекаут в ya make=)
А вот взять товарищей из Qt, у них мультирепа. Вот я хочу переименовать функцию из QtCore которая используется в другом сабмодуле. Это надо добавить функцию-обертку, закоммитить, пойти в другой модуль, заюзать враппер там, закоммитить, пойти в QtCore и наконец переименовать функцию, избавившись от обертки, закоммитить. Не слишком ли много действий для такой простой задачи?
Не, я не спорю, что при должном тулинге можно сделать это и на мультирепах, но проблема в том что и в случае монорепы и в случае мультирепы этот тулинг нужен (ни то ни другое не является серебрянной пулей и не работает из коробки) — в силу тех или иных причин Яндекс выбрал монорепу и связанный с ней тулинг. Утверждать, что монорепа — говно, «забыв» о необходимости (другого) тулинга для мультирепы — это писать фигню, потому что складывается впечатление что в Яндексе дурачки, а вот мультирепа все проблемы решит из коробки.
Ого, ничего себе. А можно подробности (в личку)?
Ну так там не один такой изъян — про монорепу фигня написана, про качество кода, про велосипеды, про легаси. То есть оно конечно в какой-то мере есть (покажите мне проект без легаси), но не это ужас-ужас достойный целой статьи.
С чем я могу согласиться — это переработки, но это как-то о-малое от всего описанного.
Мой изначальный поинт в том что не надо принимать на веру всё что пишут в интернетах и автор может быть (скажем мягко) не совсем объективен.
Да, во всякую дичь легче поверить — я когда читал всё это поймал себя на мысли «ну нихрена себе там у джавистов», но, поразмыслив, всё же решил, что слова автора надо делить примерно на 10. Например его поинт про то что на маке/венде не собирается разбивается о то, что это и не нужно делать ибо неудобно — яндексовая система сборки позволяет собирать удаленно на (линуксовых) серверах. Зачем собирать 2 часа утилиту если можно собрать ее за 10 минут на сервере? Опять же, когда я устраивался я всё это выяснил заранее и не стал брать Мак (вероятно, зря).
Если бы я до сих пор работал в Маркете и был в курсе что там в команде джавистов я бы мог подтвердить или опровергнуть описанное в статье. Из того, что я видел и где я работал — ничего подобного и близко не было.
Я работал в каком-то другом маркете и ничего подобного описанному в статье у нас не было. Либо всё за 2 года ТАК испортилось, либо автор слегка (совсем чуть-чуть) преувеличивает проблемы.
Представим теоретическую ситуацию что в статье — ложь. Что должно делать руководство в этом случае? Ну проведут они расследование, выяснят, что переработок нет или почти нет, статический анализ есть и на венде люди прекрасно работают, а человек просто обиделся на что-то, вот и пишет всякое. А потом другой человек прочитал это и не пошел работать в Яндекс, основываясь на недостоверных/неполных данных. Кто в этой теоретической ситуации выиграл?
Вы это говорите на основании собственного опыта?
Кто плюсует мне тоже интересно. Это достаточно забавно и интересно читать, но всё же ценность таких статей околонулевая (ИМХО) по сравнению с техническими статьями.
Ну вот прочитает человек такую статью, решит что Яндекс говно и не пойдет туда. Кому от этого лучше? Человеку, который не получит полезный опыт создания scalable систем? Яндексу, который не получит (возможно) ценного сотрудника?
Мне кажется, это в первую очередь не очень читаемо, тормознутость — отдельная проблема.
Правда ваша, компилятор мог бы форсить noexcept как это делается для const.
Тем не менее, в clang-tidy имеется проверка bugprone-exception-escape, которая, судя по документации, как раз призвана ловить случаи, когда кидается исключение там где его не должно быть. Если у кого есть опыт использования этой проверки — поделитесь, пожалуйста.
Если да, то у меня для вас плохие новости — либо у вас где-то есть барьер, который маскирует проблему, либо вы просто ещё не нашли багу.
Ключевое слово volatile не спасает от проблем многопоточности на relaxed-ordered архитектурах, потому что инструкции может переставлять процессор, а не компилятор (точнее, это могут делать оба, но volatile запрещает только второму).
Другое дело, что стандарт «нормального языка» ничего не говорит о многопоточности и memory ordering (поправьте, если ошибаюсь), а значит оставляет вас и компилятор в серой зоне — компилятор может вам помочь и напихать барьеров памяти, видя volatile, а может и не помогать и тогда ваш код будет содержать трудноотлаживаемую багу.