SD>> Пишут во всякие там глобальные переменные CC>Ты забываешь про диск, сеть, shared memory, etc
То есть те самые side effects. Ты серьезно сейчас о коде на языке Go, который полон такой дряни? Впрочем, и на любых других языках подобный кошмар не поощряется.
CC> Куда именно — знает только функция дайте_мне_чего_то_там у себя внутри.
Но она же знает каждый раз ОДИНАКОВО, то есть БЕЗ side effects? Стало быть, повторяя ТОТ ЖЕ запрос, ты получаешь ТОТ ЖЕ ответ? Если нет, то тут уже тебе не искючения нужны, а полная запись трейса (для чего существуют инструменты типа tracing debugger, но из применение ограничено только таким софтом, где есть реальные причины делать функции с побочными эффектами).
CC>Т.е. ошибка таки ловится на каждой подфункции а не где то вверху со всех скопом?
Только в функциях, которые вызывают побочные эффекты (то есть их поведение не детерминировано). При грамотном проектировании этих функций крайне мало, а то и вовсе нет. Многие мощные языки программирования (особенно функциональные) только так и предлагают работать. Это намного эффективнее, чем заниматься идиотизмом дебаггинга недетерминированного поведения.
Здравствуйте, SkyDance, Вы писали:
SD>Но она же знает каждый раз ОДИНАКОВО
Она тебе выдаст одинаковый ответ, но получить его внутри может по разному. И свалиться внутри может тоже по разному.
SD> Если нет, то тут уже тебе не искючения нужны, а полная запись трейса
Банальные коды ошибок с логгингом сразу по месту возникновения и пробросом наверх прекрасно справляются.
SD>Только в функциях, которые вызывают побочные эффекты
В куда бОльшем колве мест.
Для начала многие сложные функции внутри data driven, для разных данных ведут себя сильно по разному, но данных этих у тебя нет и по privacy причинам быть не может. Следовательно только стек бесполезен, надо контекст, причём такой, которые не разглашает юзерских данных. Просить репро банально некого, потому как тебе долетает только обезличенная телеметрия — ты банально не знаешь у кого из сотен миллионов пользователей сие случилось.
Добро пожаловать в реальный мир.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, m2user, Вы писали:
Pzz>>Я пишу на нём системный софтварий.
M>Я недавно в теме про Carbon lang интересовался разработкой библиотек на Go с целью использования их из других ЯП. M>И вроде как способ есть и с примерами, но судя по комментам есть какие-то препятствия? M>https://rsdn.org/forum/flame.comp/8731366.1
На Go можно делать вполне приличные C-callable DLL-ки. Но есть один нюанс, который всё портит. Дело в том, что в одном процессе два рантайма Go ужиться не могут. Причем они не подерутся с треском, что было бы хить понятни, а тихой сапой выцарапают друг другу глаза.
Поэтому пока такая DLL-ка в процессе одна, все ОК. А если их несколько, или если сам процесс Go-шный, начинаются непонятные глюки. Да еще и разные, в зависимости от OS.
Здравствуйте, CreatorCray, Вы писали:
SD>>В процессе пролета будет накоплен стек CC>Этого крайне мало. Надо куда больше контекста. CC>Более того сие нихрена не работает в компилируемых языках с оптимизаЙцией и инлайнингом.
Go умеет в инлайнинг и рождает при этом, в панике, прекраснейшие стеки.
Тем не менее, это не повод отдавать все ошибки наверх. Там с ними нифига не разберутся, а просто красиво распечатают стек и отправят это еще выше наверх, человеческому пользователю, чтобы он разбирался.
Здравствуйте, CreatorCray, Вы писали:
SD>>Мне при виде такого сразу хочется руки оторвать тем, кто не понимает, что такое "обработка ошибок". CC>Ну давай, покажи класс: большой стек вылетел потому что где то в глубине сибирских руд pread вернул ENOENT. CC>Где, какой, что делалось, что читалось, зачем?
При каких вообще условиях pread может вернуть ENOENT?
CC>Она тебе выдаст одинаковый ответ, но получить его внутри может по разному. И свалиться внутри может тоже по разному.
Еще раз: функция либо детерминированная, либо зависит от побочных эффектов. Если там "по-разному", суть детерминированность отсутствует, то или ее нужно зарефакторить (если это кишочки, которые не поросли контрактами API) и сделать детерминированной. Если же контракт гвоздями прибит — вырвать волос с головы проектировщика за такой "дизайн", и, увы, перехватывать пролетающее исключение (оно может быть как в виде ли исключения, так return code, который по сути есть проносимое врукопашную исключение) в целях дальнейшего его проброса с дополнительными данными о том, что именно пошло недетерминированно, и почему.
CC>Банальные коды ошибок с логгингом сразу по месту возникновения и пробросом наверх прекрасно справляются.
То есть ты вместо хорошего детерминированного дизайна снова полагаешься на побочные эффекты ("логирование"). И если оно сломано, отфильтровано или засемплировано, — good luck debugging. Нет, это хреновый дизайн. В хорошем дизайне функции работают детерминированно, и из результат зависит только от входных данных. Где это невозможно (скажем, нужно что-то прочитать из другой системы), приходится добавлять метаданные в пролетающее исключение (типа, "спросили у другой системы какой-то параметр, она в тот момент вернула ХХХ").
CC>В куда бОльшем колве мест.
Нет, только в недетерминированных функциях. Которые, кстати, давно уже объявлены злом. Только совсем уж дремучие кодеры не в курсе про функциональный подход.
CC>Для начала многие сложные функции внутри data driven, для разных данных ведут себя сильно по разному, но данных этих у тебя нет и по privacy причинам быть не может.
Да чем бы они ни были driven, или функция чистая (pure), то есть зависит только от входных данных, либо нет. Если это вынужденная грязь, то либо рефакторинг, либо продолжай ставить подпорки (добавлять метаданные).
CC>Добро пожаловать в реальный мир.
Это не реальный мир, а строго огороженные вольеры в зоопарке К счастью, в современном мире есть куда более надежные и качественные подходы к проектированию. Но, понятно, застрявшие во времена "классной сишечки", этак середины 80х, вряд ли смогут осознать.
Pzz>Тем не менее, это не повод отдавать все ошибки наверх. Там с ними нифига не разберутся, а просто красиво распечатают стек и отправят это еще выше наверх, человеческому пользователю, чтобы он разбирался.
Правильно. Ошибки нужно обрабатывать там, где их МОЖНО обработать. Обработать — это не "залогировать и кинуть дальше", а сделать некое осмысленное действие. Скажем, если это ошибка типа "объект не был создан", но ошибку можно исправить путем создания дефолтного объекта, — на самом нижнем уровне где это можно сделать, там и обработать.
Но если "обработка ошибок" заключается в показе диалога юзеру, то и исключение должно пролетать до того места, где этот диалог можно показать. Ловить его 10 раз по дороге и перезапускать с потерей оригинального контекста — жжуть и happy debugging.
Здравствуйте, Pzz, Вы писали:
Pzz>Go умеет в инлайнинг и рождает при этом, в панике, прекраснейшие стеки.
Это ж детский сад а не полноценный инлайнинг тогда
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Pzz, Вы писали:
Pzz>При каких вообще условиях pread может вернуть ENOENT?
В том случае прилетело через четвёртые руки.
Т.е. на три уровня ниже файловой системы, на которой лежал тот самый файл. Даже не в том же стеке.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, vsb, Вы писали:
vsb>И в пресловутом го 99.9% ошибок обрабатываются ровно так же — на самом верху. А во всех остальных местах просто return err
В теории да, но на практике (гошной) не стоит так делать.
Люди написали даже линтеры, которые запрещают "просто return err".
Здравствуйте, SkyDance, Вы писали:
CC>>Она тебе выдаст одинаковый ответ, но получить его внутри может по разному. И свалиться внутри может тоже по разному. SD>Еще раз: функция либо детерминированная, либо зависит от побочных эффектов. Если там "по-разному", суть детерминированность отсутствует, то или ее нужно зарефакторить (если это кишочки, которые не поросли контрактами API) и сделать детерминированной. Если же контракт гвоздями прибит — вырвать волос с головы проектировщика за такой "дизайн", и, увы, перехватывать пролетающее исключение (оно может быть как в виде ли исключения, так return code, который по сути есть проносимое врукопашную исключение) в целях дальнейшего его проброса с дополнительными данными о том, что именно пошло недетерминированно, и почему.
Какое вычисление(ну ладно, польза) без side effect'ов? Смысл программ тогда теряется. Ох уж эти аппологеты фп.
CC>>Банальные коды ошибок с логгингом сразу по месту возникновения и пробросом наверх прекрасно справляются. SD>То есть ты вместо хорошего детерминированного дизайна снова полагаешься на побочные эффекты ("логирование"). И если оно сломано, отфильтровано или засемплировано, — good luck debugging. Нет, это хреновый дизайн. В хорошем дизайне функции работают детерминированно, и из результат зависит только от входных данных. Где это невозможно (скажем, нужно что-то прочитать из другой системы), приходится добавлять метаданные в пролетающее исключение (типа, "спросили у другой системы какой-то параметр, она в тот момент вернула ХХХ").
И как добавлять эти метаданные без перехвата исключения на месте? Кстати, это ровно то состояние, которое
имеет в виду Креатор. Или что-то похожее.
CC>>В куда бОльшем колве мест. SD>Нет, только в недетерминированных функциях. Которые, кстати, давно уже объявлены злом. Только совсем уж дремучие кодеры не в курсе про функциональный подход.
CC>>Добро пожаловать в реальный мир. SD>Это не реальный мир, а строго огороженные вольеры в зоопарке К счастью, в современном мире есть куда более надежные и качественные подходы к проектированию. Но, понятно, застрявшие во времена "классной сишечки", этак середины 80х, вряд ли смогут осознать.
Это именно реальный мир. В огороженном вольере сидять как раз программисты на фп языках. Ну или
в очень неплохо адаптированных под конкретные вещи языках типа Эрланг. Все остальные вынуждены работать
с разного рода io операциями, где могут быть всякие сюрпризы.
Здравствуйте, SkyDance, Вы писали:
SD>Но если "обработка ошибок" заключается в показе диалога юзеру, то и исключение должно пролетать до того места, где этот диалог можно показать. Ловить его 10 раз по дороге и перезапускать с потерей оригинального контекста — жжуть и happy debugging.
Есть механизмы, которые позволяют не терять оригинальный контекст\стек.
S>Какое вычисление(ну ладно, польза) без side effect'ов?
Return value, конечно же. И дело в "апологетстве", а в минимизации мест, где происходят side effects — для того, чтобы отладка всего этого не стала кошмаром. Дело в том, что любой side effect по сути своей является ничем иным как использованием "глобальной переменной". Которые ровно за этот самый недетерминизм и ругают.
S>И как добавлять эти метаданные без перехвата исключения на месте?
В тех местах, где таки надо снабдить пролетающее исключение — хватай, добавляй метаданные, прокидывай дальше.
Таких мест должно быть очень мало. Потому что если их много, отладка такой программы будет настоящим адом. Все-таки, эффективное программирование возможно только тогда, когда программа детерминированно делает что от нее ожидается. А не валится с рандомной диагностикой.
S>Это именно реальный мир. В огороженном вольере сидять как раз программисты на фп языках. Ну или
ФП тут не при чем, это вопрос грамотного дизайна. Детерминированное поведение ровно так же ожидается и от функций на все том же С++. Собственно, на этом базируется все авто-тестирование — подаются те самые детерминированные "моки", которые детерминированно возвращают ожидаемое значение.
Если совсем уж простой пример привести, если функции на языке С++ передать все данные, и никакие другие глобальные переменные та функция не использует, ее поведение должно быть детерминировано. Легко тестируемо, и вообще, о такой функции легко рассуждать (reasoning). Даже если кому-то поначалу сложно научиться (ну как же так, всю жисть глобальные переменные дергали, а тут вдруг низ-зя), это таки вопрос освоения мощных инструментов. Речь, разумеется, о тех участках кода, где эти инструменты применимы (это подавляющее большинство non-performance-critical кода).
Здравствуйте, SkyDance, Вы писали:
SD>Таких мест должно быть очень мало.
В реальности же их очень много.
SD> Потому что если их много, отладка такой программы будет настоящим адом.
Если всему давать пролетать — да.
Потому использовать исключения для обработки обычных ошибок это геморрой.
SD> Все-таки, эффективное программирование возможно только тогда, когда программа детерминированно делает что от нее ожидается.
В сферовакууме, где ошибок не случается, а оборудование всегда идеально работает, ага.
SD>ФП тут не при чем, это вопрос грамотного дизайна.
SD> Детерминированное поведение ровно так же ожидается и от функций на все том же С++.
Никто не гарантирует что то, что твоя функция вызывает, не вернёт ошибку. Ты не в вакууме, ты сидишь над большой кучей другого кода, под которым ещё и железо, под которым всякие нестабильные physical meduiums с интерференцией и рандомными bit flips.
SD>Собственно, на этом базируется все авто-тестирование — подаются те самые детерминированные "моки", которые детерминированно возвращают ожидаемое значение.
Это вообще ортогонально.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Чем хуже код, тем больше, ага.
CC>Потому использовать исключения для обработки обычных ошибок это геморрой.
В кривых системах, само собой.
CC>Никто не гарантирует что то, что твоя функция вызывает, не вернёт ошибку.
Не вернет. А если вернет (через исключение), то там весь нужный контекст. Расширять контекст нужно только там, где, блин, нужно его расширять (потому что поведение недетерминированное).
Здравствуйте, Буравчик, Вы писали:
vsb>>И в пресловутом го 99.9% ошибок обрабатываются ровно так же — на самом верху. А во всех остальных местах просто return err
Б>В теории да, но на практике (гошной) не стоит так делать. Б>Люди написали даже линтеры, которые запрещают "просто return err".
Ну в последних версиях стало возможно return fmt.Errorf("bla failed: %w", err), пишут так теперь. Теперь не только раскрутка стека появилась, но и кривоватый стектрейс, уже прогресс. Или о чём речь?
Здравствуйте, ononim, Вы писали:
O>хуже
On a bright side: выглядеть они стали моложе и веселее
O>ну или так
Тут надо видимо знать какой то контекст, не понятно где лопата
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Pzz>Поэтому пока такая DLL-ка в процессе одна, все ОК. А если их несколько, или если сам процесс Go-шный, начинаются непонятные глюки. Да еще и разные, в зависимости от OS.
For plugins at load time it takes extra steps to find exisiting Go runtime(s) and attach various metadata (tables) to the existing ones.
For c-shared build mode, it currently doesn't do that. I think there is no fundamental reason that this couldn't be done. But it needs time to make it work.
M>For plugins at load time it takes extra steps to find exisiting Go runtime(s) and attach various metadata (tables) to the existing ones.
M>For c-shared build mode, it currently doesn't do that. I think there is no fundamental reason that this couldn't be done. But it needs time to make it work.
Собрать вместе, наверное, сложно. Потому, что разные версии рантайма могут использовать разные внутренние форматы.
Лучше бы наоборот, сделали строгую изоляцию. DLL-ка ведь экспортирует сишный, а не гошный интерефейс. Это значит, что она не может породить внутри себя гошный объект и выставить наружу указатель на него, а может выставлять только сишные функции, которые сами уж знают, как добраться до объектов, припрятанных внутри DLL-ки.
И я туда как-то раз заглянул N лет назад. Проблема в том, как гошный рантайм добирается до thread-local storage системных нитей. Они там хитрые ребята, на используют публичных интерфейсов, а знают, где ось хранит дескриптор нити, его формат и в какое место в него вписаться. Но место это в дескрипторе нити одно, что в линухе, что в венде, и если системная нить может побывать в двух рантаймах, то тут-то они за это место и подерутся.
Вот. И доделать эту изиляцию не кажется столь уж невозможным, и не должно вроде это и произвидилельность особо просадить, но дальше надо уже довольно далеко вглубиь копать, а у меня руки не дошли...