Самый главный обман, в который попадает офисный разработчик, когда от него требуют четких сроков, и четкого соблюдения сроков — это то, что зарплату он получает за часы работы, а требуют от него уже фактического выполнения задач. Оплата за выполненные задачи — это вообще-то из другой области
Интересная мысль… Не задумывался о ней.
Если провести какие-то параллели с прошлым, глубоким прошлым человечества, то почасовую/посменную оплату труда получали люди, чей труд был линеен и легко измерим — шахтеры, ткачи, ну и так далее. Условному художнику или строителю моста вроде как платили гонорар за всю работу.
Тут завидовать нечему. Если вы внимательно читали (и если я верно передал мысль), то дело не в том, что все кругом покрыто рантаймовыми проверками и ни один баг не прокрадется, а в том, что оно покрывается в какой-то мере, и из этого авторами делаются далекоидущие выводы и обещания. При том что, повторюсь, наличие рантаймовых проверок — как раз самый яркий повод вставить тесты этих самых проверок.
Я примерно так и понял, просто пример вышел очень контринтуитивный — обычно «extern» используется для указания того, что данная переменная определена (и память под нее выделена) в каком-то другом модуле, а тут мы пытаемся связаться с переменными в этом же модуле (при том, что они и так видны, будучи глобальными в рамках модуля). При этом, повторюсь, странно, что компилятор вообще не задает вопросов о том, к какой именно переменной мы обращаем.
На мой взгляд любое автоматизированное тестирование лучше, чем никакое. А в embedded, по моим наблюдениям, оно в основном никакое.
По моим наблюдениям это связано во-первых с большей загруженностью эмбедеров (я об этом уже говорил не раз), а во-вторых с тем, что так или иначе реализованные элементы защитного программирования (а то ж у нас же эмбед, куда без него!), красной нитью проходящие через всю программу, де-факто дезавуируют необходимость в юнит-тестировании, по крайней мере на уровне досужих рассуждений (и конечно это обязывает автора их проверять как-то, иначе без тестов эти защиты все равно непонятно как работают). Собственно об этом вам выше Indemsys совершенно искренне пишет.
Очеь много непонятных терминов применяете. Не из embedded.
Именно что из embedded. И что там непонятного вы увидели?
Перечислите хотя бы вы десяток «чистых» функций
Вот вам одна:
int CalcSomething(int a, int b)
{
return (a - b)/b;
}
«Чистая» она в том смысле, что не имеет защитных проверок, например самой банальной — на равенство b нулю.
Вообще тестирование такая важная вещь что лучше его встраивать в релизный код как это и делается в отвественных системах
Я выше потому и упомянул «защитное программирование во все поля», что это другая концепция, другой способ написания программы в целом, и как раз таки работоспособность защит тем более требует проверки.
Так было до C++11, начиная с C++11 они должны иметь internal linkage
Пожалуй вы правы, наверное только так можно понять эту вставку здесь:
Even though names in an unnamed namespace may be declared with external linkage, they are never accessible from other translation units because their namespace name is unique. (until C++11)
Unnamed namespaces as well as all namespaces declared directly or indirectly within an unnamed namespace have internal linkage, which means that any name that is declared within an unnamed namespace has internal linkage. (since C++11)
Хотя все же точный механизм неочевиден.
Но… тут не без сюрпризов. Вот здесь:
godbolt.org/z/yL2WUT
и clang и gcc линкуют к extern i только i, объявленную как static, если строчку с ее объявлением закомментировать, получим ошибку линковки
Эм… Весь код расположен в одном модуле, стало быть оба определения модуле-локальных переменных i во-первых не должны транслироваться наружу (и тогда объявление extern int i вообще непонятно какой смысл имеет, причем его можно безболезненно удалить), а во-вторых они ambiguous по определению, компилятор обязан ругаться в соответствии со стандартом (все по той же ссылке выше). Это что за хрень такая?
Ну все же просто — либо у вас защитное программирование во все поля (и существует доказательство безопасности, например), либо вы пишете чистые функции (я не про ФП, «чистые» — в смысле «без излишеств»), а дальше отлавливаете ошибки во время отладки и эксплуатации и покрываете конкретные участки кода конкретными тестами, чтобы те же самые ошибки больше не повторялись. Кажется глупым тестировать код на ошибку, которую только что исправили, но это на самом деле нормально, это то же самое, как системная работа над risk management file. Если вы просто ошибку исправите, то даже сам факт ее существования когда-то потонет в коммитах и тикетах.
Отличная статья! Правда огромная, и с первого раза ее осилить невозможно. Впрочем все ваши предыдущие статьи и комменты по теме юнит-тестирования в МК я читал уже, так что как-нибудь на свежую голову и эту статью осилю. :)
Холиварить насчет необходимости юнит-тестов бесполезно, поскольку противники либо просто не в теме (и это в коллективах обычно становится проблемой амбассадора, а не противников), либо просто искренне не имеют тех проблем, о которых все пишут (причем, serious, они могут просто не допускать тех ошибок, ради которых все это нужно, либо умеют быстро их находить, а реально сложные ошибки все равно лежат в сфере интеграционного тестирования). А вот найти «серебряную пулю» и всех заставить ее использовать без оговорок было бы интересно. Кажется на эту роль только googletest претендует, но это только для плюсов, а для Си особо ничего и нет (MinUnit конечно не тестовый фреймворк, а фигня).
Все сущности, которые оказываются в анонимном пространстве имен, всегда имеют internal linkage
Эмм, я возможно ошибаюсь, но когда-то я уже с этим разбирался, и, нет, у них не internal linkage в чистом виде. Просто имя сущности оказывается при трансляции гарантированно уникальным и для него не находится соответствий при линковке. В этом смысле анонимные пространства имен не являются полным аналогом static-сущностей единицы трансляции (хотя в интернете часто именно так и пишут), но результат в общем оказывается один и тот же.
Самое трешовое, когда процедура назначена на утро, и ты встаешь в 4:30 утра, чтобы выпить очередные 2 литра гребаного Фортранса… Едва ли не самое худшее утро в жизни.
которую многие оценивают как большой фейл, ибо попытка его использования ведёт к сильному падению производительности, потому что блоки больно горячие и вызывают просадку частот ниже базовой?
Тем не менее Интел безо всяких пинков внедрял много разных интересных вещей типа AVX2 например, тратили деньги на историю любви с Альтерой, так что они как раз отнюдь не та компания, которая будет ВАЗ-2105 выпускать без изменений, если нет повода. Но конечно откровенно рисковать бюджетом и рвать зад в отсутствие конкурентов никто не будет, потому я и согласился с тем, что конкуренция во благо. Причем я не думаю, что Интел что-то принципиально новое сейчас придумывает, скорее достает из загашника то, что было аккуратно придумано в «тучные годы». Скажем прямо — не все конторы так умеют.
Ну, справедливости ради Интел никогда не почивал на лаврах, но, да, конкуренция всегда во благо. Я бы даже сказал, что среди «прочих» конкуренция слабее.
Спасибо за ответ!
2) Ну, я догадался, что используется конечная разность, вопрос в том, куда записывается (Yi-Yi-1) — в i-й столбец, или в i+1-й? Ответ наверное очевиден (и может быть вообще нет разницы), но я решил переспросить.
3) Ну то есть просто берете гауссово ядро и каждый пиксель им обрабатываете? Радиус подбирается опытным путем очевидно?
4) Ну, да, кумулятивная сумма так и определяется. Я просто пытаюсь понять, как вы используете эти суммы. То есть в i-й пиксель вы записываете сумму все производных в той же строке до позиции i?
Интересная мысль… Не задумывался о ней.
Если провести какие-то параллели с прошлым, глубоким прошлым человечества, то почасовую/посменную оплату труда получали люди, чей труд был линеен и легко измерим — шахтеры, ткачи, ну и так далее. Условному художнику или строителю моста вроде как платили гонорар за всю работу.
Ну вот это как раз и контринтуитивно для меня. Ни разу не использовал extern для обращения к переменным внутри того же модуля )))
И это поведение в самом деле очень странное… Просто убиться веником.
По моим наблюдениям это связано во-первых с большей загруженностью эмбедеров (я об этом уже говорил не раз), а во-вторых с тем, что так или иначе реализованные элементы защитного программирования (а то ж у нас же эмбед, куда без него!), красной нитью проходящие через всю программу, де-факто дезавуируют необходимость в юнит-тестировании, по крайней мере на уровне досужих рассуждений (и конечно это обязывает автора их проверять как-то, иначе без тестов эти защиты все равно непонятно как работают). Собственно об этом вам выше Indemsys совершенно искренне пишет.
Именно что из embedded. И что там непонятного вы увидели?
Вот вам одна:
«Чистая» она в том смысле, что не имеет защитных проверок, например самой банальной — на равенство b нулю.
Я выше потому и упомянул «защитное программирование во все поля», что это другая концепция, другой способ написания программы в целом, и как раз таки работоспособность защит тем более требует проверки.
Пожалуй вы правы, наверное только так можно понять эту вставку здесь:
Хотя все же точный механизм неочевиден.
Эм… Весь код расположен в одном модуле, стало быть оба определения модуле-локальных переменных i во-первых не должны транслироваться наружу (и тогда объявление extern int i вообще непонятно какой смысл имеет, причем его можно безболезненно удалить), а во-вторых они ambiguous по определению, компилятор обязан ругаться в соответствии со стандартом (все по той же ссылке выше). Это что за хрень такая?
Холиварить насчет необходимости юнит-тестов бесполезно, поскольку противники либо просто не в теме (и это в коллективах обычно становится проблемой амбассадора, а не противников), либо просто искренне не имеют тех проблем, о которых все пишут (причем, serious, они могут просто не допускать тех ошибок, ради которых все это нужно, либо умеют быстро их находить, а реально сложные ошибки все равно лежат в сфере интеграционного тестирования). А вот найти «серебряную пулю» и всех заставить ее использовать без оговорок было бы интересно. Кажется на эту роль только googletest претендует, но это только для плюсов, а для Си особо ничего и нет (MinUnit конечно не тестовый фреймворк, а фигня).
Эмм, я возможно ошибаюсь, но когда-то я уже с этим разбирался, и, нет, у них не internal linkage в чистом виде. Просто имя сущности оказывается при трансляции гарантированно уникальным и для него не находится соответствий при линковке. В этом смысле анонимные пространства имен не являются полным аналогом static-сущностей единицы трансляции (хотя в интернете часто именно так и пишут), но результат в общем оказывается один и тот же.
БрежневСандики, застой, ностальгия! В 2011 году я мечтал купить себе i5-2500K, но денег пожалел. :)Однако многие аплодируют стоя )))
2) Ну, я догадался, что используется конечная разность, вопрос в том, куда записывается (Yi-Yi-1) — в i-й столбец, или в i+1-й? Ответ наверное очевиден (и может быть вообще нет разницы), но я решил переспросить.
3) Ну то есть просто берете гауссово ядро и каждый пиксель им обрабатываете? Радиус подбирается опытным путем очевидно?
4) Ну, да, кумулятивная сумма так и определяется. Я просто пытаюсь понять, как вы используете эти суммы. То есть в i-й пиксель вы записываете сумму все производных в той же строке до позиции i?
Тут на одном экране работа, на другом уведомления с Хабра в почте сыпятся, бывает всякое ))