"Визуальное программирование" в среде builder'а подразумевает автоматическую генерацию кода на выходе (для каждого фрейма и так три файла — h,cpp,dfm). Если продолжать данную традицию, то можно ожидать, что также возможно создание соответствующего unit-теста (*_Test.cpp или что-то подобное) для каждого компонента, в том же автоматическом режиме. Я сам с таким не сталкивался, но допускаю, что если можно сгенерировать по шаблону некий код, то можно сгенерировать и unit-тест для него.
и еще такой момент, коллега — судя по вашему описанию, вы широко используете возможности по генерации кода, предоставляемые средой. Тестовый код по отношению к тестируемому идет как 1:2/3/4… (в зависимости от сложности логики тестируемого кода). Если вы до сих пор не столкнулись с удобным инструментом для автоматической генерации unit-тестов в своей среде, то вряд ли он существует. Захотите ли вы вручную создавать тесты для того кода, который нагенерит ваша среда? Посчитайте LOC вашего проекта и умножьте его на 2, для начала.
Если я правильно понимаю, то вы используете предопределенные компоненты в качестве базовых, создаете на их основе собственные, которые связываете мышкой и немножко с клавиатуры. Полагаем, что предопределенные компоненты уже оттестированы, и нам их тестировать нет нужды. Значит нужно протестировать заданные свойства вновь созданных компонентов их связи между собой. Вряд ли легковесный CppUnit встроен с C++ Builder настолько, что все можно сделать также мышкой, поэтому придется делать ручками с клавиатуры. Т.к. для строительства приложения вы используете компоненты, то unit-тестирование — самое то. Мокируем окружение, создаем собственную компоненту и проверяем те свойства, которые мы напрограммировали для этой компоненты мышкой и с клавы. Главный вопрос — есть ли подходящая билиотека для создания моков? Сообщество говорит, что есть opmock. Сам я подобных связок не пробовал, но начал бы копать с этого.
всё работает без единой строчки кода.
подозреваю, что если как следует поискать в файлах проекта, то все-таки код можно будет обнаружить :)
Ни один разработчик в здравом уме и трезвой памяти при разработке сложных приложений (> 100K LOC, например) не станет отрицать необходимость использования тестирования вообще и модульного тестирования (unit tests) в частности.
К сожалению перфекционистам в M2 опасно — она еще очень сырая, неоднородная по реализации система с незавершенными архитектурными решениями (те же репозитории, все еще полностью не заменившие ресурс-модели). Любой владелец магазина на М2 — доброневольный бета-тестер. Работа над выправлением этой ситуации идет, но сможет ли команда разработчиков ее выправить — вопрос открытый. Я бы поставил на них, если бы они отказались от обратной совместимости (которой и так нет) и провели генеральную чистку и реструктуризацию кода и данных, но это стало бы уже М3. Таких маневров community может и не выдержать, а без своих расширений Magento превратится в тот же Shopify, только еще и на своем "железе". Ну а пока разработчики борются со сложностью и, судя по тому, что тесты на Travis'е у них не проходят уже около месяца, борьба идет ожесточенная.
Хотя, она все же чертовски интересная:)
А вот тут полностью согласен :) Весьма любопытный пример распределенной разработки приложений.
Богатая функциональность, получаемая "из-коробки" — это раз. Большое кол-во расширений основного функционала, созданных сторонними разработчиками — это два. Все еще значительное community (best practice & support, как отметил коллега Sergiy) — это три. И плюс куча времени и средств закопанного в нее как разработчиками (основного функционала и расширений), так и владельцами магазинов.
И да, профит в даном случае огромный есть только тогда когда систему заведомо будут поддерживать очень долгое время и большое количество разных людей.
Как я говорил, преобразование только в объекты, аналогичные java-beans (вот определение). Там нет ничего, кроме акцессоров. Добавление новых типов объектов и новых свойств в существующие типы не влияет на существующий код. Никакого god object'а я не вижу — тупой функционал.
принцип единственной обязанности (англ. Single responsibility principle) обозначает, что каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс. Все его сервисы должны быть направлены исключительно на обеспечение этой обязанности.
Какую еще обязанность вы обнаружили в моем примере, кроме преобразования ассоциативного массива в объект заданного типа?
Входные данные — это ассоциативный массив и имя класса в который этот ассоциативный массив должен быть преобразован. Не вижу ничего страшного в том, что входные данные могут быть разных типов. А результат у меня один — объект. SRP не ограничивает кол-во и тип входных/выходных данных, насколько мне известно.
Допускаю, что лучший пример рекурсии для вас — вычисление факториала. И могу полностью с вами согласиться, что на "лучшем примере рекурсии" нет необходимости мокать собственно саму рекурсивную функцию, там нет никаких зависимостей и всего-то два прохода — первый и последний. Но в моем примере таких проходов 4 и плюс пара зависимостей, чье поведение нужно также замокать на соответствующую глубину. И если вы мне укажите, в каком месте моего примера нарушен благословенный SRP, то я буду премного вам благодарен и пересмотрю свои взгляды как минимум для данного примера. Пока же "нарушение SRP" в примере настолько же доказанный факт, как и "дублирование".
"Визуальное программирование" в среде builder'а подразумевает автоматическую генерацию кода на выходе (для каждого фрейма и так три файла — h,cpp,dfm). Если продолжать данную традицию, то можно ожидать, что также возможно создание соответствующего unit-теста (*_Test.cpp или что-то подобное) для каждого компонента, в том же автоматическом режиме. Я сам с таким не сталкивался, но допускаю, что если можно сгенерировать по шаблону некий код, то можно сгенерировать и unit-тест для него.
и еще такой момент, коллега — судя по вашему описанию, вы широко используете возможности по генерации кода, предоставляемые средой. Тестовый код по отношению к тестируемому идет как 1:2/3/4… (в зависимости от сложности логики тестируемого кода). Если вы до сих пор не столкнулись с удобным инструментом для автоматической генерации unit-тестов в своей среде, то вряд ли он существует. Захотите ли вы вручную создавать тесты для того кода, который нагенерит ваша среда? Посчитайте LOC вашего проекта и умножьте его на 2, для начала.
Если я правильно понимаю, то вы используете предопределенные компоненты в качестве базовых, создаете на их основе собственные, которые связываете мышкой и немножко с клавиатуры. Полагаем, что предопределенные компоненты уже оттестированы, и нам их тестировать нет нужды. Значит нужно протестировать заданные свойства вновь созданных компонентов их связи между собой. Вряд ли легковесный CppUnit встроен с C++ Builder настолько, что все можно сделать также мышкой, поэтому придется делать ручками с клавиатуры. Т.к. для строительства приложения вы используете компоненты, то unit-тестирование — самое то. Мокируем окружение, создаем собственную компоненту и проверяем те свойства, которые мы напрограммировали для этой компоненты мышкой и с клавы. Главный вопрос — есть ли подходящая билиотека для создания моков? Сообщество говорит, что есть opmock. Сам я подобных связок не пробовал, но начал бы копать с этого.
подозреваю, что если как следует поискать в файлах проекта, то все-таки код можно будет обнаружить :)
А вы пробовали DUnit? Да, он давно не менялся, но и Delphi не вчера родилось. Может вполне юзабельно окажется.
Извините, пожалуйста, не хотел никого испугать.
Если рассуждать с точки зрения TDD, то вы совершенно правы.
Ну как же не сказано? Вот, в самом начале:
Спасибо, коллега. Внес изменения в код примера.
К сожалению перфекционистам в M2 опасно — она еще очень сырая, неоднородная по реализации система с незавершенными архитектурными решениями (те же репозитории, все еще полностью не заменившие ресурс-модели). Любой владелец магазина на М2 —
доброневольный бета-тестер. Работа над выправлением этой ситуации идет, но сможет ли команда разработчиков ее выправить — вопрос открытый. Я бы поставил на них, если бы они отказались от обратной совместимости (которой и так нет) и провели генеральную чистку и реструктуризацию кода и данных, но это стало бы уже М3. Таких маневров community может и не выдержать, а без своих расширений Magento превратится в тот же Shopify, только еще и на своем "железе". Ну а пока разработчики борются со сложностью и, судя по тому, что тесты на Travis'е у них не проходят уже около месяца, борьба идет ожесточенная.А вот тут полностью согласен :) Весьма любопытный пример распределенной разработки приложений.
Богатая функциональность, получаемая "из-коробки" — это раз. Большое кол-во расширений основного функционала, созданных сторонними разработчиками — это два. Все еще значительное community (best practice & support, как отметил коллега Sergiy) — это три. И плюс куча времени и средств закопанного в нее как разработчиками (основного функционала и расширений), так и владельцами магазинов.
© vpodorozh
В пределе всё всё равно сводится к маш. кодам. Но люди почему-то не любят их использовать.
полагаю, раз есть "по умолчанию", значит есть и явный способ задать timeout.
Т.е., получается, что выставленный timeout никакого отношения к измеренному выводу времени работы
age()не имеет? В одном случаеtimeout выставляется на компиляцию кода, а в другом
на выполнение кода (т.е. на создание объекта и его метода
age()).Выполнение же метода
ageпроисходит здесьи никакими timeout'ами не ограничено.
В таком случае, непонятно, что имел в виду коллега slayerhabr, демонстрируя свой пример :(
Запустил код slayerhabr под node v4.2.6, указал timeout как и положено — в
runInNewContext. Имею результатНикакого отвала по timeout'у не наблюдаю. Складывается впечатление, что timeout отрабатывает как минимум не всегда.
Как я говорил, преобразование только в объекты, аналогичные java-beans (вот определение). Там нет ничего, кроме акцессоров. Добавление новых типов объектов и новых свойств в существующие типы не влияет на существующий код. Никакого god object'а я не вижу — тупой функционал.
Какую еще обязанность вы обнаружили в моем примере, кроме преобразования ассоциативного массива в объект заданного типа?
Входные данные — это ассоциативный массив и имя класса в который этот ассоциативный массив должен быть преобразован. Не вижу ничего страшного в том, что входные данные могут быть разных типов. А результат у меня один — объект. SRP не ограничивает кол-во и тип входных/выходных данных, насколько мне известно.
Допускаю, что лучший пример рекурсии для вас — вычисление факториала. И могу полностью с вами согласиться, что на "лучшем примере рекурсии" нет необходимости мокать собственно саму рекурсивную функцию, там нет никаких зависимостей и всего-то два прохода — первый и последний. Но в моем примере таких проходов 4 и плюс пара зависимостей, чье поведение нужно также замокать на соответствующую глубину. И если вы мне укажите, в каком месте моего примера нарушен благословенный SRP, то я буду премного вам благодарен и пересмотрю свои взгляды как минимум для данного примера. Пока же "нарушение SRP" в примере настолько же доказанный факт, как и "дублирование".
Спасибо за ответ, коллега. Когда мне нужен будет пример поверхностности и/или догматизма — я буду о вас вспоминать.
Коллега Fesor, я не вижу ни вашего кода, исключающего излишнее дублирование в моем примере, ни ваших вопросов по постановке задачи.