Я имею в виду — окей, предположим, что этот вопрос — имитация задания от реального заказчика. Есть вероятность, что заказчику на самом деле нужно что-то другое, но он уже сам себе придумал, что для этого нужно определить, в какую сторону течет вода в трубе.
Т.е. есть смысл попробовать докопаться до первопричины, может быть все проще? Ну или таким образом отсечь заведомо неподходящие способы (разрушительные, например).
И он должен позволять программисту описывать всё то, что может исполнять процессор.
Ну, в С, например, нет циклических сдвигов, которые в процессорах есть очень часто. И многих специфических вещей типа POPCNT или CLZ тоже нет. И что делать?
Хорошо, если компилятор догадывается заменить функцию одной инструкцией, но он ведь не обязан.
А compiler-specific вещи — не часть языка, они не стандартизированы...
В embedded постоянно пользуюсь кольцевыми буферами и скользящим медианным фильтром (самодельными). Пару раз юзал самодельный map, потому что почти все структуры данных из стандартной библиотеки С++ используют кучу.
Но при этом считаю, что знать классические алгоритмы (типа сортировок и поиска в глубину) — это просто интересно.
Ну так, для использования HAL'a нужно HAL тащить, а для регистров напрямую — не нужно :)
К тому же, когда он только появлялся, им пользоваться было решительно невозможно.
Еще такой вопрос, не про библиотеку, а скорее про свертки.
Может быть у меня мозги не обучены еще в таких понятиях думать, но мне все время кажется, что свертки хорошо смотрятся, если цикл:
по всей коллекции целиком
затрагивает либо каждый элемент по отдельности, либо только соседние элементы, либо элементы, подчиняющиеся какому-то паттерну
не удаляет элементы
В то время как обычный цикл таких ограничений лишен — я могу спокойно удалить третий, пятый и 19-ый элемент, при этом начав проход со второго, а закончив на 3 элемента раньше конца.
Понятное дело, что так писать нехорошо и это скорее всего симптом плохого дизайна, но все же?
Спасибо, интересно! А как со длительностью компиляции обстоят дела у вашей библиотеки? Оригинальные ranges Ниблера компилируются прям ооочень долго (вроде бы в основном из-за самодельных концептов).
Штош. У вас процесс разработки существенно отличается от нашего, поэтому вам я ничего возразить по сути не могу.
Единственное, что если бы вы это описали сразу, то ваши, скорее всего, замечания не воспринимались бы так резко :)
Если вы доверяете своим рефлексам — окей, могу только позавидовать. Я себе не доверяю, потому что раз за разом совершаю глупые ошибки (только вот находить их все сложнее и сложнее).
Поэтому стараюсь по максимуму перекладывать проверки на инструменты — компилятор, тесты, программы для статического анализа и т.д. И по возможности привлекать коллег на код-ревью.
Так что лично мне просто страшно писать в одиночку; я знаю, что буду косячить.
Генерированный код тестить, конечно, дело неблагодарное; наверное, логичнее было бы тестить собственно модели в матлабе? Но как это делать (и нужно ли) — не знаю; матлабом не пользуюсь. Так что тут вам видней.
Я собственно в вопросительном тоне и пишу. Автор отвечает что я неправильно спрашиваю. Как вам это?
Я не знаю, какое мое сообщение вы умудрились так прочесть; я пытаюсь уточнить, что же вы хотите увидеть — но на мои комментарии вы отвечать перестали… ну ладно, как вам будет угодно.
Я все-таки продолжу комментировать, пусть не для вас, но для других читателей :)
И как у автора везде сквозит — это всего лишь административные меры для навязывания стиля остальным программистам.
Да, отчасти это так. И в командной разработке единство стиля — это очень важно; члены команды должны иметь возможность понимать код друг друга.
Как могут рухнуть такие мелкие функции если вы их сами написали, сами поддерживаете и сами рефакторите? Это что не то уже с памятью. Так тут не помогут никакие тесты.
Но если у вас реально сложные функции с большим количеством состояний, то юнит-тестирование предложенное здесь — детский лепет.
Нуэмм… как бы вам объяснить?
Очень нежелательно писать огромные сложные функции со множеством состояний — их трудно читать, их трудно тестировать.
Поэтому такие функции разбиваются на отдельные более простые части, которые тестируются по отдельности.
А затем тестируются все целиком.
Если пользоваться методикой "протестил — удалил тест" или "протестил компонент вручную", то вы либо доверяете своей памяти, либо ведете какой-то журнал протестированного… видимо.
Я своей памяти не настолько доверяю, а журнал вести лень — зачем, вот же тесты есть. Зачем их удалять-то?
Как могут рухнуть такие мелкие функции если вы их сами написали, сами поддерживаете и сами рефакторите
Как раз-таки не факт, что их я поддерживать буду сам! Я же не один работаю.
А упомянутые вами авторы занимаются проблемами командного программирования. Но есть просто огромная разница между методами командного программирования и индивидуального.
Допустим. Но вы же не считаете, что в embedded не существует командной разработки?
К тому же, даже в индивидуальной разработке тесты — очень полезная штука. Я не знаю, может быть у вас абсолютная память, но я, глядя на свой код пятилетней давности, далеко не всегда могу понять его сходу.
А тесты — это как еще один слой документации, как небольшие примеры использования кода и демонстрация его поведения.
Они тестируется в режиме Test-driven development. И оставлять рудименты в виде юнит-тестов после этого не нужно.
Ээээ, то есть вы пишете в стиле TDD — а потом тесты удаляете? Но ведь тесты — это гарантия того, что новые изменения не сломают старый функционал.
Или по-вашему TDD — это когда вы что-то написали, вручную проверили — работает, все?
И некоторые ваши функции без аргументов.
Т.е. к ним неприменимо юнит-тестирование, как тут его описывают.
Что же за тестирование у вас в таком случае?
Эти функции могут опираться на какое-то глобальное состояние; не только чистые (в всмысле ФП) функции можно тестировать — хотя, конечно, проще.
Я, скажем, почти всегда пишу объекты (у которых есть внутреннее состояние), поэтому тестирую тоже объекты, а не функции по отдельности.
Моделирование — это реализация некоторых известных вам аспектов поведения с возможностью коррекции, ради чего моделирование и устраивается.
Если вы «тестируете» датчик которого не держали в руках, то это моделирование датчика, а не тестирование.
Да, разумеется, в каком-то смысле тесты — это модель датчика по его спецификации.
Но я тестирую не датчик, а я тестирую свой код.
Когда я получу датчик в руки я, разумеется, проверю работу кода с ним — и скорее всего выяснится, что я какой-то нюанс не учел. Но мой опыт показывает, что это исправляется достаточно быстро. При этом в тестах я уже смоделировал кучу ситуаций, которые в реальности получать очень долго/трудно — всякие обрывы связей в очень неудачные моменты, испорченные пакеты, мусорные данные и т.д.
Как вам сказать… я очень часто вижу людей, которые настолько плохо понимают, что такое разработка, что даже не понимают, что не так. Они не слышали ни про контроль версий, ни про комментарии, ни про что вообще. И им нормально, они не видят проблемы. Ну типа работает же.
Им пофиг, что функции на 3000 строк невозможно читать — их код просто никто никогда не читает, кроме них самих.
ибо думает что никто не занимается тем же чем и он
Не знаю, почему вы так решили.
Я не привел "список функций", потому что все еще не могу понять, что конкретно вы хотите увидеть в этом списке.
Вас не затруднит дать свое определение "тестирования"? И "имитационного моделирования"? Мне кажется у нас какое-то расхождение в терминологии.
Отличная статья! Правда огромная, и с первого раза ее осилить невозможно. Впрочем все ваши предыдущие статьи и комменты по теме юнит-тестирования в МК я читал уже, так что как-нибудь на свежую голову и эту статью осилю. :)
Я польщен :) Статью, наверное, можно рассматривать или как тутор или как какой-нибудь справочник и не читать целиком — я просто постарался зафиксировать как можно больше "набитых шишек".
они могут просто не допускать тех ошибок, ради которых все это нужно, либо умеют быстро их находить, а реально сложные ошибки все равно лежат в сфере интеграционного тестирования).
Согласен, неоднократно наблюдал таких людей и прям не понимаю, как они это делают. Я постоянно косячу без тестов ._. Причем с каждым годом косяки по сути те же, но находить их становится все сложнее и сложнее… Очень странный эффект.
А вот найти «серебряную пулю» и всех заставить ее использовать без оговорок было бы интересно. Кажется на эту роль только googletest претендует, но это только для плюсов, а для Си особо ничего и нет (MinUnit конечно не тестовый фреймворк, а фигня).
Если бы я сейчас выбирал фреймворк и не был ограничен упоротыми компиляторами для МК, то наверное взял бы Catch2; но эт дело вкуса.
А MinUnit… ну, это, конечно, не полноценный фреймворк, но он очень хорош как пример ( я даже студентам показывал что-то похожее в три-четыре строчки).
На мой взгляд любое автоматизированное тестирование лучше, чем никакое. А в embedded, по моим наблюдениям, оно в основном никакое.
Я имею в виду — окей, предположим, что этот вопрос — имитация задания от реального заказчика. Есть вероятность, что заказчику на самом деле нужно что-то другое, но он уже сам себе придумал, что для этого нужно определить, в какую сторону течет вода в трубе.
Т.е. есть смысл попробовать докопаться до первопричины, может быть все проще? Ну или таким образом отсечь заведомо неподходящие способы (разрушительные, например).
А зачем вообще определять направление течения жидкости? Ну типа, какая разница?
FreeCommander; я сам не фанат, но коллега-поклонник тотала вроде доволен.
Ну, в С, например, нет циклических сдвигов, которые в процессорах есть очень часто. И многих специфических вещей типа POPCNT или CLZ тоже нет. И что делать?
Хорошо, если компилятор догадывается заменить функцию одной инструкцией, но он ведь не обязан.
А compiler-specific вещи — не часть языка, они не стандартизированы...
В embedded постоянно пользуюсь кольцевыми буферами и скользящим медианным фильтром (самодельными). Пару раз юзал самодельный map, потому что почти все структуры данных из стандартной библиотеки С++ используют кучу.
Но при этом считаю, что знать классические алгоритмы (типа сортировок и поиска в глубину) — это просто интересно.
Tenacious D in The Pick of Destiny
Ну так, для использования HAL'a нужно HAL тащить, а для регистров напрямую — не нужно :)
К тому же, когда он только появлялся, им пользоваться было решительно невозможно.
Ох, ностальгия… Такой классный был файлик, генерил код на регистрах! А с кубом для этого весь HAL тащить приходится.
А можно ли вместо регулярного покоса травы высадить низкорослую траву?
Уболтали :) Спасибо!
Здорово!
Еще такой вопрос, не про библиотеку, а скорее про свертки.
Может быть у меня мозги не обучены еще в таких понятиях думать, но мне все время кажется, что свертки хорошо смотрятся, если цикл:
В то время как обычный цикл таких ограничений лишен — я могу спокойно удалить третий, пятый и 19-ый элемент, при этом начав проход со второго, а закончив на 3 элемента раньше конца.
Понятное дело, что так писать нехорошо и это скорее всего симптом плохого дизайна, но все же?
Спасибо, интересно! А как со длительностью компиляции обстоят дела у вашей библиотеки? Оригинальные ranges Ниблера компилируются прям ооочень долго (вроде бы в основном из-за самодельных концептов).
Штош. У вас процесс разработки существенно отличается от нашего, поэтому вам я ничего возразить по сути не могу.
Единственное, что если бы вы это описали сразу, то ваши, скорее всего, замечания не воспринимались бы так резко :)
Если вы доверяете своим рефлексам — окей, могу только позавидовать. Я себе не доверяю, потому что раз за разом совершаю глупые ошибки (только вот находить их все сложнее и сложнее).
Поэтому стараюсь по максимуму перекладывать проверки на инструменты — компилятор, тесты, программы для статического анализа и т.д. И по возможности привлекать коллег на код-ревью.
Так что лично мне просто страшно писать в одиночку; я знаю, что буду косячить.
Генерированный код тестить, конечно, дело неблагодарное; наверное, логичнее было бы тестить собственно модели в матлабе? Но как это делать (и нужно ли) — не знаю; матлабом не пользуюсь. Так что тут вам видней.
Я не знаю, какое мое сообщение вы умудрились так прочесть; я пытаюсь уточнить, что же вы хотите увидеть — но на мои комментарии вы отвечать перестали… ну ладно, как вам будет угодно.
Я все-таки продолжу комментировать, пусть не для вас, но для других читателей :)
Да, отчасти это так. И в командной разработке единство стиля — это очень важно; члены команды должны иметь возможность понимать код друг друга.
Нуэмм… как бы вам объяснить?
Очень нежелательно писать огромные сложные функции со множеством состояний — их трудно читать, их трудно тестировать.
Поэтому такие функции разбиваются на отдельные более простые части, которые тестируются по отдельности.
А затем тестируются все целиком.
Если пользоваться методикой "протестил — удалил тест" или "протестил компонент вручную", то вы либо доверяете своей памяти, либо ведете какой-то журнал протестированного… видимо.
Я своей памяти не настолько доверяю, а журнал вести лень — зачем, вот же тесты есть. Зачем их удалять-то?
Как раз-таки не факт, что их я поддерживать буду сам! Я же не один работаю.
Допустим. Но вы же не считаете, что в embedded не существует командной разработки?
К тому же, даже в индивидуальной разработке тесты — очень полезная штука. Я не знаю, может быть у вас абсолютная память, но я, глядя на свой код пятилетней давности, далеко не всегда могу понять его сходу.
А тесты — это как еще один слой документации, как небольшие примеры использования кода и демонстрация его поведения.
Ээээ, то есть вы пишете в стиле TDD — а потом тесты удаляете? Но ведь тесты — это гарантия того, что новые изменения не сломают старый функционал.
Или по-вашему TDD — это когда вы что-то написали, вручную проверили — работает, все?
Эти функции могут опираться на какое-то глобальное состояние; не только чистые (в всмысле ФП) функции можно тестировать — хотя, конечно, проще.
Я, скажем, почти всегда пишу объекты (у которых есть внутреннее состояние), поэтому тестирую тоже объекты, а не функции по отдельности.
Да, разумеется, в каком-то смысле тесты — это модель датчика по его спецификации.
Но я тестирую не датчик, а я тестирую свой код.
Когда я получу датчик в руки я, разумеется, проверю работу кода с ним — и скорее всего выяснится, что я какой-то нюанс не учел. Но мой опыт показывает, что это исправляется достаточно быстро. При этом в тестах я уже смоделировал кучу ситуаций, которые в реальности получать очень долго/трудно — всякие обрывы связей в очень неудачные моменты, испорченные пакеты, мусорные данные и т.д.
Как вам сказать… я очень часто вижу людей, которые настолько плохо понимают, что такое разработка, что даже не понимают, что не так. Они не слышали ни про контроль версий, ни про комментарии, ни про что вообще. И им нормально, они не видят проблемы. Ну типа работает же.
Им пофиг, что функции на 3000 строк невозможно читать — их код просто никто никогда не читает, кроме них самих.
Какое уж там защитное программирование -_-'
Пожалуй, я могу только позавидовать вашему опыту.
Я в основном вижу совсем другое ._.
Не знаю, почему вы так решили.
Я не привел "список функций", потому что все еще не могу понять, что конкретно вы хотите увидеть в этом списке.
Вас не затруднит дать свое определение "тестирования"? И "имитационного моделирования"? Мне кажется у нас какое-то расхождение в терминологии.
Я польщен :) Статью, наверное, можно рассматривать или как тутор или как какой-нибудь справочник и не читать целиком — я просто постарался зафиксировать как можно больше "набитых шишек".
Согласен, неоднократно наблюдал таких людей и прям не понимаю, как они это делают. Я постоянно косячу без тестов ._. Причем с каждым годом косяки по сути те же, но находить их становится все сложнее и сложнее… Очень странный эффект.
Если бы я сейчас выбирал фреймворк и не был ограничен упоротыми компиляторами для МК, то наверное взял бы Catch2; но эт дело вкуса.
А MinUnit… ну, это, конечно, не полноценный фреймворк, но он очень хорош как пример ( я даже студентам показывал что-то похожее в три-четыре строчки).
На мой взгляд любое автоматизированное тестирование лучше, чем никакое. А в embedded, по моим наблюдениям, оно в основном никакое.